/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Andrea Aime - GeoSolutions
*/
package org.geowebcache.diskquota.jdbc;
import java.util.Arrays;
import java.util.List;
/**
* Oracle dialect for the quota store, compared to the basic one creates index organized tables
* and uses the Oracle specific syntax to get the pages with the oldest access time and lowest
* access frequency
*
* @author Andrea Aime - GeoSolutions
*/
public class OracleDialect extends SQLDialect {
// Oracle's Number type has a maximum precision of 38
static final int MAX_NUMBER_PRECISION = 38;
static int numberPrecision(int n) {
return Math.min(n, MAX_NUMBER_PRECISION);
}
public OracleDialect() {
TABLE_CREATION_MAP.put("TILESET", Arrays.asList( //
"CREATE TABLE ${schema}TILESET (\n" + //
" KEY VARCHAR("+TILESET_KEY_SIZE+") PRIMARY KEY,\n" + //
" LAYER_NAME VARCHAR("+LAYER_NAME_SIZE+"),\n" + //
" GRIDSET_ID VARCHAR("+GRIDSET_ID_SIZE+"),\n" + //
" BLOB_FORMAT VARCHAR("+BLOB_FORMAT_SIZE+"),\n" + //
" PARAMETERS_ID VARCHAR("+PARAMETERS_ID_SIZE+"),\n" + //
" BYTES NUMBER("+numberPrecision(BYTES_SIZE)+") DEFAULT 0 NOT NULL\n" + //
") ORGANIZATION INDEX", //
"CREATE INDEX TILESET_LAYER ON TILESET(LAYER_NAME)" //
));
TABLE_CREATION_MAP.put("TILEPAGE", Arrays.asList(
"CREATE TABLE ${schema}TILEPAGE (\n"
+ //
" KEY VARCHAR("+TILEPAGE_KEY_SIZE+") PRIMARY KEY,\n"
+ //
" TILESET_ID VARCHAR("+TILESET_KEY_SIZE+") REFERENCES ${schema}TILESET(KEY) ON DELETE CASCADE,\n"
+ //
" PAGE_Z SMALLINT,\n" + //
" PAGE_X INTEGER,\n" + //
" PAGE_Y INTEGER,\n" + //
" CREATION_TIME_MINUTES INTEGER,\n" + //
" FREQUENCY_OF_USE FLOAT,\n" + //
" LAST_ACCESS_TIME_MINUTES INTEGER,\n" + //
" FILL_FACTOR FLOAT,\n" + //
" NUM_HITS NUMBER("+numberPrecision(NUM_HITS_SIZE)+")\n" + //
") ORGANIZATION INDEX", //
"CREATE INDEX TILEPAGE_TILESET ON TILEPAGE(TILESET_ID)",
"CREATE INDEX TILEPAGE_FILL_FACTOR ON TILEPAGE(FILL_FACTOR)",
"CREATE INDEX TILEPAGE_FREQUENCY ON TILEPAGE(FREQUENCY_OF_USE DESC)",
"CREATE INDEX TILEPAGE_LAST_ACCESS ON TILEPAGE(LAST_ACCESS_TIME_MINUTES DESC)"));
}
@Override
protected void addEmtpyTableReference(StringBuilder sb) {
sb.append("FROM DUAL");
}
public String getLeastFrequentlyUsedPage(String schema, List<String> layerParamNames) {
StringBuilder sb = new StringBuilder("SELECT * FROM (");
sb.append("SELECT TILESET_ID, PAGE_X, PAGE_Y, PAGE_Z, CREATION_TIME_MINUTES FROM ");
if (schema != null) {
sb.append(schema).append(".");
}
sb.append("TILEPAGE WHERE FILL_FACTOR > 0 ");
sb.append("AND TILESET_ID IN (");
sb.append("SELECT KEY FROM ");
if (schema != null) {
sb.append(schema).append(".");
}
sb.append("TILESET WHERE LAYER_NAME IN (");
for (int i = 0; i < layerParamNames.size(); i++) {
sb.append(":" + layerParamNames.get(i));
if (i < layerParamNames.size() - 1) {
sb.append(", ");
}
}
sb.append(")) ORDER BY FREQUENCY_OF_USE ASC");
sb.append(") WHERE ROWNUM <= 1");
return sb.toString();
}
public String getLeastRecentlyUsedPage(String schema, List<String> layerParamNames) {
StringBuilder sb = new StringBuilder("SELECT * FROM (");
sb.append("SELECT TILESET_ID, PAGE_X, PAGE_Y, PAGE_Z, CREATION_TIME_MINUTES FROM ");
if (schema != null) {
sb.append(schema).append(".");
}
sb.append("TILEPAGE WHERE FILL_FACTOR > 0 ");
sb.append("AND TILESET_ID IN (");
sb.append("SELECT KEY FROM ");
if (schema != null) {
sb.append(schema).append(".");
}
sb.append("TILESET WHERE LAYER_NAME IN (");
for (int i = 0; i < layerParamNames.size(); i++) {
sb.append(":" + layerParamNames.get(i));
if (i < layerParamNames.size() - 1) {
sb.append(", ");
}
}
sb.append(")) ORDER BY LAST_ACCESS_TIME_MINUTES ASC");
sb.append(") WHERE ROWNUM <= 1");
return sb.toString();
}
}