-
Notifications
You must be signed in to change notification settings - Fork 77
Prototype based on blackhole_fdw and c -> java calls #534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
/** | ||
* Additional content for `EXPLAIN x...` | ||
* | ||
* No details yet. | ||
*/ | ||
public interface FDWExplainState { | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
/** | ||
* The Foreign Data Wrapper. | ||
* | ||
* This is the highest-level abstraction, e.g., for information | ||
* contained in S3 files. | ||
* | ||
* It could also capture an abstract concept, e.g., one FDW | ||
* to capture multiple authentication implementations. | ||
* | ||
* There may be multiple instances of a single FOREIGN DATA WRAPPER. | ||
*/ | ||
public interface FDWForeignDataWrapper { | ||
|
||
/** | ||
* The instances unique ID. It should be used to maintain a cache. | ||
* @return | ||
*/ | ||
default Long getId() { return null; } | ||
|
||
/** | ||
* Return a copy of the options provided to `CREATE FOREIGN DATA WRAPPER...` | ||
* @return | ||
*/ | ||
default Map<String, String> getOptions() { return Collections.emptyMap(); }; | ||
|
||
/** | ||
* Validate a set of options against an existing instance. There should be | ||
* a similar static method before creating a new instance. | ||
* | ||
* @param options | ||
* @return | ||
*/ | ||
default boolean validateOptions(Map<String, String> options) { return true; }; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
import java.sql.ResultSetMetaData; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
/** | ||
* The Foreign Table | ||
* | ||
* This is the lowest-level abstraction, e.g., a specific | ||
* S3 file. | ||
* | ||
* There may be multiple instances of a Foreign Table | ||
* for a single Foreign Server. | ||
*/ | ||
public interface FDWForeignTable { | ||
|
||
/** | ||
* The instances unique ID. It should be used to maintain a cache. | ||
*/ | ||
default Long getId() { return null; } | ||
|
||
/** | ||
* Return a copy of the options provided to `CREATE FOREIGN TABLE...` | ||
* @return | ||
*/ | ||
default Map<String, String> getOptions() { return Collections.emptyMap(); }; | ||
|
||
/** | ||
* Validate a set of options against an existing instance. There should be | ||
* a similar static method before creating a new instance. | ||
* | ||
* @param options | ||
* @return | ||
*/ | ||
default boolean validateOptions(Map<String, String> options) { return true; }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as for the wrapper Indeed, most of the methods of this interface are methods proper to an FDW implementation. It's only methods like |
||
|
||
/** | ||
* Create an object used for query planning. | ||
* | ||
* @param user | ||
* @return | ||
*/ | ||
FDWPlanState newPlanState(FDWUser user); | ||
|
||
/** | ||
* Create an object used for SELECT statements. | ||
* @param user | ||
* @return | ||
*/ | ||
FDWScanState newScanState(FDWUser user, boolean explainOnly); | ||
|
||
// values from PlannerInfo *root, RelOptInfo *baserel | ||
// BUT NOT foreigntableoid | ||
void getRelSize(); | ||
|
||
/* | ||
static void blackholeGetForeignPaths(PlannerInfo *root, | ||
RelOptInfo *baserel, | ||
Oid foreigntableid); | ||
*/ | ||
|
||
// values from PlannerInfo *root, RelOptInfo *baserel | ||
// BUT NOT foreigntableoid | ||
void getForeignPaths(); | ||
|
||
/** | ||
* Is this table updatable by this user? | ||
* | ||
* @param user | ||
* @return | ||
*/ | ||
default boolean isUupdatable(FDWUser user) { return false; } | ||
|
||
/** | ||
* Does this table support concurrent access? | ||
* @return | ||
*/ | ||
default boolean supportsConcurrency() { return false; } | ||
|
||
/** | ||
* Does this table support asynchronous queries? | ||
* @return | ||
*/ | ||
default boolean supportsAsyncOperations() { return false; } | ||
|
||
/** | ||
* Collect statistics used by the query optimizer. | ||
* This can be supported for read-only tables. | ||
* | ||
* Details TBD | ||
*/ | ||
default void analyze() { } | ||
|
||
/** | ||
* Compact the data, if appropriate. | ||
* This should be a noop for read-only tables. | ||
* | ||
* Details TBD. | ||
*/ | ||
default void vacuum() { } | ||
|
||
/** | ||
* Get the table's schema. This information | ||
* will be used when executing `IMPORT FOREIGN SCHEMA...` | ||
* | ||
* @return | ||
*/ | ||
default ResultSetMetaData getMetaData() { return null; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you assuming here that JDBC metadata will be adequate to describe the foreign table? Are you assuming further that the foreign connection will involve JDBC? The JDBC |
||
|
||
/** | ||
* Estimate the number of rows. | ||
* | ||
* @return | ||
*/ | ||
default long getRows() { return 0; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
public interface FDWPlanState { | ||
|
||
// values from PlannerInfo *root, RelOptInfo *baserel. | ||
// the PlannerInfo is only used in advanced queries. | ||
void open(); | ||
|
||
void close(); | ||
|
||
default long getRows() { return 0; } | ||
|
||
default FDWUser getUser() { return null; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
import java.util.Map; | ||
|
||
public interface FDWScanState { | ||
/** | ||
* The database has already performed an initial check for | ||
* the user's permission to execute SELECT - but our java | ||
* code may impose additional requirements. | ||
* | ||
* The minimal implementation just adds the ability to check | ||
* whether * the user is authorized. (The current FDWUser is | ||
* transparently * passed to the appropriate method.) | ||
* | ||
* A more advanced implementation would allow us to | ||
* add row and column filtering beyond what will already | ||
* be done by the database. | ||
*/ | ||
default boolean isAuthorizedUser() { return true; } | ||
|
||
/** | ||
* Verify that we have a valid configuration. | ||
* | ||
* No external resources should be accessed if | ||
* the `explainOnly` flag is true. (It's okay to | ||
* check a file exists and is readable but it should | ||
* not be opened. A REST service can have its hostname | ||
* verified but it should not be called. | ||
* | ||
* If the `explainOnly` flag is false than external | ||
* resources can be accessed in order to verify | ||
* that it's a valid URL and we have valid credentials. | ||
* However all external resources should be released | ||
* before this method exits. | ||
*/ | ||
void open(boolean explainOnly); | ||
|
||
// values from TableTupleType. It is an element | ||
// of the ForeignScanState mentioned above. | ||
Map<String, Object> next(); | ||
|
||
/** | ||
* Reset scan to initial state. | ||
*/ | ||
void reset(); | ||
|
||
/** | ||
* Release resources | ||
*/ | ||
void close(); | ||
|
||
default FDWExplainState explain() { return null; } | ||
|
||
default FDWUser getUser() { return null; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.postgresql.pljava.fdw; | ||
|
||
import java.sql.DatabaseMetaData; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
|
||
/** | ||
* The Foreign Server | ||
* | ||
* This is the middle-level abstraction, e.g., a specific | ||
* AWS account with access to the required resources. | ||
* | ||
* There may be multiple instances of a Foreign Server | ||
* for a single Foreign Data Wrapper. | ||
*/ | ||
public interface FDWServer { | ||
|
||
/** | ||
* The instances unique ID. It should be used to maintain a cache. | ||
*/ | ||
default Long getId() { return null; } | ||
|
||
/** | ||
* Return a copy of the options provided to `CREATE FOREIGN SERVER...` | ||
* @return | ||
*/ | ||
default Map<String, String> getOptions() { return Collections.emptyMap(); }; | ||
|
||
/** | ||
* Validate a set of options against an existing instance. There should be | ||
* a similar static method before creating a new instance. | ||
* | ||
* @param options | ||
* @return | ||
*/ | ||
default boolean validateOptions(Map<String, String> options) { return true; }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as for wrapper |
||
|
||
/** | ||
* Get the server's entire schema. This can be useful | ||
* information even if the backend only gets the | ||
* schema for individual tables. | ||
* | ||
* (It's not clear since the backend struct supports | ||
* foreign keys but I don't think the individual | ||
* ResultSetMetadata includes that information.) | ||
* | ||
* @return | ||
*/ | ||
default DatabaseMetaData getMetaData() { return null; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as for foreign table |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this interface you have combined behaviors of a PostgreSQL catalog object (such as a
getOptions
method to report what options have been assigned in PostgreSQL DDL) with behaviors that belong to some chosen FDW implementation (such as avalidateOptions
method that knows which options are valid for that chosen implementation.Those concerns are distinct. There should be (and already is) a catalog object interface that takes care of retrieving the foreign data wrapper's
options
and other particulars from the catalog. It's PL/Java's job to supply that and take care of the housekeeping, like caching it by itsoid
, making sure it isn't stale, and so on.It's a particular FDW implementation's job to implement some different interface that specifies methods for validating the options, along with whatever other behavior an FDW implementation needs to supply.