public abstract class JDBCTranslator extends java.lang.Object implements ADQLTranslator
Implementation of ADQLTranslator
which translates ADQL queries in SQL queries.
It is already able to translate all SQL standard features, but lets abstract the translation of all
geometrical functions. So, this translator must be extended as PostgreSQLTranslator
and
PgSphereTranslator
are doing.
Note: Its default implementation of the SQL syntax has been inspired by the PostgreSQL one. However, it should work also with SQLite and MySQL, but some translations might be needed (as it is has been done for PostgreSQL about the mathematical functions).
PgSphereTranslator
extends PostgreSQLTranslator
and is able to translate geometrical
functions according to the syntax given by PgSphere. But it can also convert geometrical types
(from and toward the database), translate PgSphere regions into STC expression and vice-versa.
PostgreSQLTranslator
overwrites the translation of mathematical functions whose some have
a different name or signature. Besides, it is also implementing the translation of the geometrical
functions. However, it does not really translate them. It is just returning the ADQL expression
(by calling getDefaultADQLFunction(ADQLFunction)
).
And so, of course, the execution of a SQL query containing geometrical functions and translated
using this translator will not work. It is just a default implementation in case there is no interest
of these geometrical functions.
In ADQL and in SQL, it is possible to tell the parser to respect the exact case or not of an identifier (schema, table or column name)
by surrounding it with double quotes. However ADQL identifiers and SQL ones may be different. In that way, the case sensitivity specified
in ADQL on the different identifiers can not be kept in SQL. That's why this translator lets specify a general rule on which types of
SQL identifier must be double quoted. This can be done by implementing the abstract function isCaseSensitive(IdentifierField)
.
The functions translating column and table names will call this function in order to surround the identifiers by double quotes or not.
So, be careful if you want to override the functions translating columns and tables!
The default behavior of this translator is to translate the ADQL "TOP" into the SQL "LIMIT" at the end of the query.
This is ok for some DBMS, but not all. So, if your DBMS does not know the "LIMIT" keyword, you should override the function
translating the whole query: translate(ADQLQuery)
. Here is its current implementation:
StringBuffer sql = new StringBuffer(translate(query.getSelect())); sql.append("\nFROM ").append(translate(query.getFrom())); if (!query.getWhere().isEmpty()) sql.append('\n').append(translate(query.getWhere())); if (!query.getGroupBy().isEmpty()) sql.append('\n').append(translate(query.getGroupBy())); if (!query.getHaving().isEmpty()) sql.append('\n').append(translate(query.getHaving())); if (!query.getOrderBy().isEmpty()) sql.append('\n').append(translate(query.getOrderBy())); if (query.getSelect().hasLimit()) sql.append("\nLimit ").append(query.getSelect().getLimit()); return sql.toString();
All ADQL functions are by default not translated. Consequently, the SQL translation is
actually the ADQL expression. Generally the ADQL expression is generic enough. However some mathematical functions may need
to be translated differently. For instance PostgreSQLTranslator
is translating differently: LOG, LOG10, RAND and TRUNC.
Note: Geometrical regions and types have not been managed here. They stay abstract because it is obviously impossible to have a generic translation and conversion ; it totally depends from the database system.
The FROM clause is translated into SQL as written in ADQL. There is no differences except the identifiers that are replaced. The tables' aliases and their case sensitivity are kept like in ADQL.
PostgreSQLTranslator
,
PgSphereTranslator
Constructor and Description |
---|
JDBCTranslator() |
Modifier and Type | Method and Description |
---|---|
static java.lang.StringBuffer |
appendIdentifier(java.lang.StringBuffer str,
java.lang.String id,
boolean caseSensitive)
Appends the given identifier to the given StringBuffer.
|
java.lang.StringBuffer |
appendIdentifier(java.lang.StringBuffer str,
java.lang.String id,
IdentifierField field)
Appends the given identifier in the given StringBuffer.
|
abstract DBType |
convertTypeFromDB(int dbmsType,
java.lang.String rawDbmsTypeName,
java.lang.String dbmsTypeName,
java.lang.String[] typeParams)
Convert any type provided by a JDBC driver into a type understandable by the ADQL/TAP library.
|
abstract java.lang.String |
convertTypeToDB(DBType type)
Convert any type provided by the ADQL/TAP library into a type understandable by a JDBC driver.
|
java.lang.String |
getColumnName(DBColumn column)
Get the DB name of the given column
|
protected java.lang.String |
getDefaultADQLFunction(ADQLFunction fct)
Gets the default SQL output for the given ADQL function.
|
protected java.lang.String |
getDefaultADQLList(ADQLList<? extends ADQLObject> list)
Gets the default SQL output for a list of ADQL objects.
|
protected java.lang.String |
getDefaultColumnReference(ColumnReference ref)
Gets the default SQL output for a column reference.
|
java.lang.String |
getQualifiedSchemaName(DBTable table)
Get the qualified DB name of the schema containing the given table.
|
java.lang.String |
getQualifiedTableName(DBTable table)
Get the qualified DB name of the given table.
|
java.lang.String |
getTableName(DBTable table,
boolean withSchema)
Get the DB name of the given table.
|
abstract boolean |
isCaseSensitive(IdentifierField field)
Tell whether the specified identifier MUST be translated so that being interpreted case sensitively or not.
|
java.lang.String |
translate(ADQLColumn column) |
java.lang.String |
translate(ADQLConstraint cons) |
java.lang.String |
translate(ADQLFunction fct) |
java.lang.String |
translate(ADQLJoin join) |
java.lang.String |
translate(ADQLList<? extends ADQLObject> list) |
java.lang.String |
translate(ADQLObject obj) |
java.lang.String |
translate(ADQLOperand op) |
java.lang.String |
translate(ADQLOrder order) |
java.lang.String |
translate(ADQLQuery query) |
java.lang.String |
translate(ADQLTable table) |
java.lang.String |
translate(Between comp) |
java.lang.String |
translate(ClauseConstraints clause) |
java.lang.String |
translate(ClauseSelect clause) |
java.lang.String |
translate(ColumnReference ref) |
java.lang.String |
translate(Comparison comp) |
java.lang.String |
translate(Concatenation concat) |
java.lang.String |
translate(Exists exists) |
java.lang.String |
translate(FromContent content) |
java.lang.String |
translate(GeometryFunction.GeometryValue<? extends GeometryFunction> geomValue) |
java.lang.String |
translate(GeometryFunction fct) |
java.lang.String |
translate(In in) |
java.lang.String |
translate(IsNull isNull) |
java.lang.String |
translate(MathFunction fct) |
java.lang.String |
translate(NegativeOperand negOp) |
java.lang.String |
translate(NotConstraint notCons) |
java.lang.String |
translate(NumericConstant numConst) |
java.lang.String |
translate(Operation op) |
java.lang.String |
translate(SelectAllColumns item) |
java.lang.String |
translate(SelectItem item) |
java.lang.String |
translate(SQLFunction fct) |
java.lang.String |
translate(StringConstant strConst) |
java.lang.String |
translate(UserDefinedFunction fct) |
java.lang.String |
translate(WrappedOperand op) |
abstract STCS.Region |
translateGeometryFromDB(java.lang.Object jdbcColValue)
Parse the given JDBC column value as a geometry object and convert it into a
STCS.Region . |
abstract java.lang.Object |
translateGeometryToDB(STCS.Region region)
Convert the given STC region into a DB column value.
|
public abstract boolean isCaseSensitive(IdentifierField field)
Tell whether the specified identifier MUST be translated so that being interpreted case sensitively or not. By default, an identifier that must be translated with case sensitivity will be surrounded by double quotes. But, if this function returns FALSE, the SQL name will be written just as given in the metadata, without double quotes.
WARNING:
An IdentifierField
object can be a SCHEMA, TABLE, COLUMN and ALIAS. However, in this translator,
aliases are translated like in ADQL (so, with the same case sensitivity specification as in ADQL).
So, this function will never be used to know the case sensitivity to apply to an alias. It is then
useless to write a special behavior for the ALIAS value.
field
- The identifier whose the case sensitive to apply is asked.public java.lang.String getQualifiedSchemaName(DBTable table)
Get the qualified DB name of the schema containing the given table.
Note:
This function will, by default, add double quotes if the schema name must be case sensitive in the SQL query.
This information is provided by isCaseSensitive(IdentifierField)
.
table
- A table of the schema whose the qualified DB name is asked.public java.lang.String getQualifiedTableName(DBTable table)
Get the qualified DB name of the given table.
Note:
This function will, by default, add double quotes if the table name must be case sensitive in the SQL query.
This information is provided by isCaseSensitive(IdentifierField)
.
table
- The table whose the qualified DB name is asked.getTableName(DBTable, boolean)
public java.lang.String getTableName(DBTable table, boolean withSchema)
Get the DB name of the given table. The second parameter lets specify whether the table name must be prefixed by the qualified schema name or not.
Note:
This function will, by default, add double quotes if the table name must be case sensitive in the SQL query.
This information is provided by isCaseSensitive(IdentifierField)
.
table
- The table whose the DB name is asked.withSchema
- true if the qualified schema name must prefix the table name, false otherwise.public java.lang.String getColumnName(DBColumn column)
Get the DB name of the given column
Note:
This function will, by default, add double quotes if the column name must be case sensitive in the SQL query.
This information is provided by isCaseSensitive(IdentifierField)
.
Caution: The given column may be NULL and in this case an empty string will be returned. But if the given column is not NULL, its DB name MUST NOT BE NULL!
column
- The column whose the DB name is asked.public final java.lang.StringBuffer appendIdentifier(java.lang.StringBuffer str, java.lang.String id, IdentifierField field)
str
- The string buffer.id
- The identifier to append.field
- The type of identifier (column, table, schema, catalog or alias ?).public static final java.lang.StringBuffer appendIdentifier(java.lang.StringBuffer str, java.lang.String id, boolean caseSensitive)
str
- The string buffer.id
- The identifier to append.caseSensitive
- true to format the identifier so that preserving the case sensitivity, false otherwise.public java.lang.String translate(ADQLObject obj) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLQuery query) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLList<? extends ADQLObject> list) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
protected java.lang.String getDefaultADQLList(ADQLList<? extends ADQLObject> list) throws TranslationException
list
- List to format into SQL.TranslationException
- If there is an error during the translation.public java.lang.String translate(ClauseSelect clause) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ClauseConstraints clause) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(SelectItem item) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(SelectAllColumns item) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ColumnReference ref) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
protected java.lang.String getDefaultColumnReference(ColumnReference ref) throws TranslationException
ref
- The column reference to format into SQL.TranslationException
- If there is an error during the translation.public java.lang.String translate(ADQLOrder order) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(FromContent content) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLTable table) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLJoin join) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLOperand op) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLColumn column) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(Concatenation concat) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(NegativeOperand negOp) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(NumericConstant numConst) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(StringConstant strConst) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(WrappedOperand op) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(Operation op) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLConstraint cons) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(Comparison comp) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(Between comp) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(Exists exists) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(In in) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(IsNull isNull) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(NotConstraint notCons) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(ADQLFunction fct) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
protected final java.lang.String getDefaultADQLFunction(ADQLFunction fct) throws TranslationException
fct
- The ADQL function to format into SQL.TranslationException
- If there is an error during the translation.public java.lang.String translate(SQLFunction fct) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(MathFunction fct) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(UserDefinedFunction fct) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(GeometryFunction fct) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public java.lang.String translate(GeometryFunction.GeometryValue<? extends GeometryFunction> geomValue) throws TranslationException
translate
in interface ADQLTranslator
TranslationException
public abstract DBType convertTypeFromDB(int dbmsType, java.lang.String rawDbmsTypeName, java.lang.String dbmsTypeName, java.lang.String[] typeParams)
dbmsType
- Type returned by a JDBC driver. Note: this value is returned by ResultSetMetadata.getColumnType(int) and correspond to a type of java.sql.TypesrawDbmsTypeName
- Full name of the type returned by a JDBC driver. Note: this name is returned by ResultSetMetadata.getColumnTypeName(int) ; this name may contain parametersdbmsTypeName
- Name of type, without the eventual parameters. Note: this name is extracted from rawDbmsTypeName.typeParams
- The eventual type parameters (e.g. char string length). Note: these parameters are extracted from rawDbmsTypeName.public abstract java.lang.String convertTypeToDB(DBType type)
Convert any type provided by the ADQL/TAP library into a type understandable by a JDBC driver.
Note: The returned DBMS type may contain some parameters between brackets.
type
- The ADQL/TAP library's type to convert.public abstract STCS.Region translateGeometryFromDB(java.lang.Object jdbcColValue) throws ParseException
Parse the given JDBC column value as a geometry object and convert it into a STCS.Region
.
Note: Generally the returned object will be used to get its STC-S expression.
Note: If the given column value is NULL, NULL will be returned.
Important note:
This function is called ONLY for value of columns flagged as geometries by
convertTypeFromDB(int, String, String, String[])
. So the value should always
be of the expected type and format. However, if it turns out that the type is wrong
and that the conversion is finally impossible, this function SHOULD throw a
jdbcColValue
- A JDBC column value (returned by ResultSet.getObject(int)).STCS.Region
if the given value is a geometry.ParseException
- If the given object is not a geometrical object
or can not be transformed into a STCS.Region
object.public abstract java.lang.Object translateGeometryToDB(STCS.Region region) throws ParseException
Convert the given STC region into a DB column value.
Note: This function is used only by the UPLOAD feature, to import geometries provided as STC-S expression in a VOTable document inside a DB column.
Note: If the given region is NULL, NULL will be returned.
region
- The region to store in the DB.ParseException
- If the given STC Region can not be converted into a DB object.