提交 cceb5a12 authored 作者: noelgrandin's avatar noelgrandin

Issue 510: Make org.h2.bnf public for consumption by external projects, patch by Nicolas Fortin

上级 5da851fe
......@@ -489,7 +489,7 @@ CREATE DOMAIN EMAIL AS VARCHAR(255) CHECK (POSITION('@', VALUE) > 1)
"Commands (DDL)","CREATE INDEX","
CREATE
{ [ UNIQUE ] [ HASH ] INDEX [ [ IF NOT EXISTS ] newIndexName ]
{ [ UNIQUE ] [ HASH ] [ SPATIAL] INDEX [ [ IF NOT EXISTS ] newIndexName ]
| PRIMARY KEY [ HASH ] }
ON tableName ( indexColumn [,...] )
","
......@@ -500,6 +500,7 @@ Hash indexes are meant for in-memory databases and memory tables (CREATE MEMORY
For other tables, or if the index contains multiple columns, the HASH keyword is ignored.
Hash indexes can only test for equality, and do not support range queries (similar to a hash table).
Non-unique keys are supported.
Spatial indexes are supported only on Geometry columns.
","
CREATE INDEX IDXNAME ON TEST(NAME)
"
......@@ -1726,9 +1727,9 @@ multiple lines long.
"
"Other Grammar","Compare","
<> | <= | >= | = | < | > | !=
<> | <= | >= | = | < | > | != | &&
","
Comparison operator. The operator != is the same as <>.
Comparison operator. The operator != is the same as <>. && means overlapping, can only be used with geometry types.
","
<>
"
......
......@@ -80,6 +80,7 @@ Change Log
</li><li>Make org.h2.util.ScriptReader throw a better exception when handling broken scripts which generate
extremely large statements.
</li><li>Fix bug with ALLOW_LITERALS=NONE, where the periodic analyze table on insert would throw an exception.
</li><li>Issue 510: Make org.h2.bnf public for consumption by external projects, patch by Nicolas Fortin
</li></ul>
<h2>Version 1.3.173 (2013-07-28)</h2>
......
......@@ -48,5 +48,7 @@ Export-Package: org.h2;version="${version}",
org.h2.jdbcx;version="${version}",
org.h2.tools;version="${version}",
org.h2.util;version="${version}",
org.h2.value;version="${version}"
org.h2.value;version="${version}",
org.h2.bnf;version="${version}" ,
org.h2.bnf.context;version="${version}"
Premain-Class: org.h2.util.Profiler
......@@ -15,7 +15,8 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;
import org.h2.server.web.DbContextRule;
import org.h2.bnf.context.DbContextRule;
import org.h2.tools.Csv;
import org.h2.util.New;
import org.h2.util.StringUtils;
......
......@@ -13,14 +13,14 @@ import org.h2.util.StringUtils;
/**
* A single terminal rule in a BNF object.
*/
class RuleElement implements Rule {
public class RuleElement implements Rule {
private final boolean keyword;
private final String name;
private Rule link;
private final int type;
RuleElement(String name, String topic) {
public RuleElement(String name, String topic) {
this.name = name;
this.keyword = name.length() == 1 || name.equals(StringUtils.toUpperEnglish(name));
topic = StringUtils.toLowerEnglish(topic);
......
......@@ -13,13 +13,13 @@ import org.h2.util.New;
/**
* Represents a sequence of BNF rules, or a list of alternative rules.
*/
class RuleList implements Rule {
public class RuleList implements Rule {
private final boolean or;
private final ArrayList<Rule> list;
private boolean mapSet;
RuleList(Rule first, Rule next, boolean or) {
public RuleList(Rule first, Rule next, boolean or) {
list = New.arrayList();
if (first instanceof RuleList && ((RuleList) first).or == or) {
list.addAll(((RuleList) first).list);
......
......@@ -11,11 +11,11 @@ import java.util.HashMap;
/**
* Represents an optional BNF rule.
*/
class RuleOptional implements Rule {
public class RuleOptional implements Rule {
private final Rule rule;
private boolean mapSet;
RuleOptional(Rule rule) {
public RuleOptional(Rule rule) {
this.rule = rule;
}
......
......@@ -11,12 +11,12 @@ import java.util.HashMap;
/**
* Represents a loop in a BNF object.
*/
class RuleRepeat implements Rule {
public class RuleRepeat implements Rule {
private final Rule rule;
private final boolean comma;
RuleRepeat(Rule rule, boolean comma) {
public RuleRepeat(Rule rule, boolean comma) {
this.rule = rule;
this.comma = comma;
}
......
......@@ -9,8 +9,8 @@ package org.h2.bnf;
import java.util.HashMap;
import java.util.HashSet;
import org.h2.server.web.DbSchema;
import org.h2.server.web.DbTableOrView;
import org.h2.bnf.context.DbSchema;
import org.h2.bnf.context.DbTableOrView;
import org.h2.util.New;
import org.h2.util.StringUtils;
......@@ -29,12 +29,12 @@ public class Sentence {
/**
* The token type for a keyword.
*/
static final int KEYWORD = 1;
public static final int KEYWORD = 1;
/**
* The token type for a function name.
*/
static final int FUNCTION = 2;
public static final int FUNCTION = 2;
private static final long MAX_PROCESSING_TIME = 100;
......@@ -63,7 +63,7 @@ public class Sentence {
/**
* Start the timer to make sure processing doesn't take too long.
*/
void start() {
public void start() {
stopAt = System.currentTimeMillis() + MAX_PROCESSING_TIME;
}
......@@ -72,7 +72,7 @@ public class Sentence {
* Processing auto-complete shouldn't take more than a few milliseconds.
* If processing is stopped, this methods throws an IllegalStateException
*/
void stopIfRequired() {
public void stopIfRequired() {
if (System.currentTimeMillis() > stopAt) {
throw new IllegalStateException();
}
......@@ -214,7 +214,7 @@ public class Sentence {
*
* @return the next token map
*/
HashMap<String, String> getNext() {
public HashMap<String, String> getNext() {
return next;
}
......
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Keeps the meta data information of a column.
* This class is used by the H2 Console.
*/
class DbColumn {
/**
* The column name.
*/
final String name;
/**
* The quoted table name.
*/
final String quotedName;
/**
* The data type name (including precision and the NOT NULL flag if
* applicable).
*/
final String dataType;
DbColumn(DbContents contents, ResultSet rs) throws SQLException {
name = rs.getString("COLUMN_NAME");
quotedName = contents.quoteIdentifier(name);
String type = rs.getString("TYPE_NAME");
int size = rs.getInt(DbContents.findColumn(rs, "COLUMN_SIZE", 7));
boolean isSQLite = contents.isSQLite;
if (size > 0 && !isSQLite) {
type += "(" + size;
int prec = rs.getInt(DbContents.findColumn(rs, "DECIMAL_DIGITS", 9));
if (prec > 0) {
type += ", " + prec;
}
type += ")";
}
if (rs.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls) {
type += " NOT NULL";
}
dataType = type;
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.bnf.context;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Keeps the meta data information of a column.
* This class is used by the H2 Console.
*/
public class DbColumn {
private final String name;
private final String quotedName;
private final String dataType;
private int position;
/**
* @return The data type name (including precision and the NOT NULL flag if
* applicable).
*/
public String getDataType() {
return dataType;
}
/**
* @return The column name.
*/
public String getName() {
return name;
}
/**
* @return The quoted table name.
*/
public String getQuotedName() {
return quotedName;
}
/**
* @return Column index
*/
public int getPosition() {
return position;
}
public DbColumn(DbContents contents, ResultSet rs) throws SQLException {
name = rs.getString("COLUMN_NAME");
quotedName = contents.quoteIdentifier(name);
String type = rs.getString("TYPE_NAME");
// A procedures column size is identified by PRECISION, for table this is COLUMN_SIZE
int precisionColumnIndex = DbContents.findColumn(rs, "PRECISION", 0);
int size;
if( precisionColumnIndex == 0 ){
size = rs.getInt(DbContents.findColumn(rs, "COLUMN_SIZE", 7));
} else {
size = rs.getInt(precisionColumnIndex);
}
position = rs.getInt("ORDINAL_POSITION");
boolean isSQLite = contents.isSQLite();
if (size > 0 && !isSQLite) {
type += "(" + size;
int prec = rs.getInt(DbContents.findColumn(rs, "DECIMAL_DIGITS", 9));
if (prec > 0) {
type += ", " + prec;
}
type += ")";
}
if (rs.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls) {
type += " NOT NULL";
}
dataType = type;
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.bnf.context;
import org.h2.util.New;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
/**
* Contains meta data information about a procedure.
* This class is used by the H2 Console.
*/
public class DbProcedure {
private final DbSchema schema;
private final String name;
private final String quotedName;
private boolean returnsResult;
private DbColumn[] parameters;
public DbProcedure(DbSchema schema, ResultSet rs) throws SQLException {
this.schema = schema;
name = rs.getString("PROCEDURE_NAME");
returnsResult = rs.getShort("PROCEDURE_TYPE") == DatabaseMetaData.procedureReturnsResult;
quotedName = schema.getContents().quoteIdentifier(name);
}
/**
* @return The schema this table belongs to.
*/
public DbSchema getSchema() {
return schema;
}
/**
* @return The column list.
*/
public DbColumn[] getParameters() {
return parameters;
}
/**
* @return The table name.
*/
public String getName() {
return name;
}
/**
* @return The quoted table name.
*/
public String getQuotedName() {
return quotedName;
}
/**
* @return True if this function return a value
*/
public boolean isReturnsResult() {
return returnsResult;
}
/**
* Read the column for this table from the database meta data.
*
* @param meta the database meta data
*/
void readParameters(DatabaseMetaData meta) throws SQLException {
ResultSet rs = meta.getProcedureColumns(null, schema.name, name, null);
ArrayList<DbColumn> list = New.arrayList();
while (rs.next()) {
DbColumn column = new DbColumn(schema.getContents(), rs);
if(column.getPosition()>0) { //Not the return type
list.add(column);
}
}
rs.close();
parameters = new DbColumn[list.size()];
// Store the parameter in the good position [1-n]
for(int i=0;i<parameters.length;i++) {
DbColumn column = list.get(i);
if(column.getPosition()>0 && column.getPosition() <= parameters.length) {
parameters[column.getPosition() - 1] = column;
}
}
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.util.New;
import org.h2.util.StringUtils;
/**
* Contains meta data information about a database schema.
* This class is used by the H2 Console.
*/
public class DbSchema {
/**
* Up to this many tables, the column type and indexes are listed.
*/
static final int MAX_TABLES_LIST_INDEXES = 100;
/**
* Up to this many tables, the column names are listed.
*/
static final int MAX_TABLES_LIST_COLUMNS = 500;
/**
* The database content container.
*/
final DbContents contents;
/**
* The schema name.
*/
final String name;
/**
* True if this is the default schema for this database.
*/
final boolean isDefault;
/**
* True if this is a system schema (for example the INFORMATION_SCHEMA).
*/
final boolean isSystem;
/**
* The quoted schema name.
*/
final String quotedName;
/**
* The table list.
*/
DbTableOrView[] tables;
DbSchema(DbContents contents, String name, boolean isDefault) {
this.contents = contents;
this.name = name;
this.quotedName = contents.quoteIdentifier(name);
this.isDefault = isDefault;
if (name.equals("INFORMATION_SCHEMA")) {
isSystem = true;
} else if (!contents.isH2 && StringUtils.toUpperEnglish(name).startsWith("INFO")) {
isSystem = true;
} else if (contents.isPostgreSQL && StringUtils.toUpperEnglish(name).startsWith("PG_")) {
isSystem = true;
} else if (contents.isDerby && name.startsWith("SYS")) {
isSystem = true;
} else {
isSystem = false;
}
}
/**
* Read all tables for this schema from the database meta data.
*
* @param meta the database meta data
* @param tableTypes the table types to read
*/
void readTables(DatabaseMetaData meta, String[] tableTypes) throws SQLException {
ResultSet rs = meta.getTables(null, name, null, tableTypes);
ArrayList<DbTableOrView> list = New.arrayList();
while (rs.next()) {
DbTableOrView table = new DbTableOrView(this, rs);
if (contents.isOracle && table.name.indexOf('$') > 0) {
continue;
}
list.add(table);
}
rs.close();
tables = new DbTableOrView[list.size()];
list.toArray(tables);
if (tables.length < MAX_TABLES_LIST_COLUMNS) {
for (DbTableOrView tab : tables) {
tab.readColumns(meta);
}
}
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.bnf.context;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.util.New;
import org.h2.util.StringUtils;
/**
* Contains meta data information about a database schema.
* This class is used by the H2 Console.
*/
public class DbSchema {
/**
* Up to this many tables, the column type and indexes are listed.
*/
public static final int MAX_TABLES_LIST_INDEXES = 100;
/**
* Up to this many tables, the column names are listed.
*/
public static final int MAX_TABLES_LIST_COLUMNS = 500;
/**
* Up to this many tables, the column names are listed.
*/
public static final int MAX_PROCEDURES_LIST_COLUMNS = 500;
/**
* The database content container.
*/
private final DbContents contents;
/**
* The schema name.
*/
public final String name;
/**
* True if this is the default schema for this database.
*/
public final boolean isDefault;
/**
* True if this is a system schema (for example the INFORMATION_SCHEMA).
*/
public final boolean isSystem;
/**
* The quoted schema name.
*/
public final String quotedName;
/**
* The table list.
*/
private DbTableOrView[] tables;
/**
* The procedures list.
*/
private DbProcedure[] procedures;
DbSchema(DbContents contents, String name, boolean isDefault) {
this.contents = contents;
this.name = name;
this.quotedName = contents.quoteIdentifier(name);
this.isDefault = isDefault;
if (name.equals("INFORMATION_SCHEMA")) {
isSystem = true;
} else if (!contents.isH2() && StringUtils.toUpperEnglish(name).startsWith("INFO")) {
isSystem = true;
} else if (contents.isPostgreSQL() && StringUtils.toUpperEnglish(name).startsWith("PG_")) {
isSystem = true;
} else if (contents.isDerby() && name.startsWith("SYS")) {
isSystem = true;
} else {
isSystem = false;
}
}
/**
* @return The database content container.
*/
public DbContents getContents() {
return contents;
}
/**
* @return The table list.
*/
public DbTableOrView[] getTables() {
return tables;
}
/**
* @return The procedure list.
*/
public DbProcedure[] getProcedures() {
return procedures;
}
/**
* Read all tables for this schema from the database meta data.
*
* @param meta the database meta data
* @param tableTypes the table types to read
*/
public void readTables(DatabaseMetaData meta, String[] tableTypes) throws SQLException {
ResultSet rs = meta.getTables(null, name, null, tableTypes);
ArrayList<DbTableOrView> list = New.arrayList();
while (rs.next()) {
DbTableOrView table = new DbTableOrView(this, rs);
if (contents.isOracle() && table.getName().indexOf('$') > 0) {
continue;
}
list.add(table);
}
rs.close();
tables = new DbTableOrView[list.size()];
list.toArray(tables);
if (tables.length < MAX_TABLES_LIST_COLUMNS) {
for (DbTableOrView tab : tables) {
tab.readColumns(meta);
}
}
}
/**
* Read all procedures in the dataBase.
* @param meta the database meta data
* @throws SQLException Error while fetching procedures
*/
public void readProcedures(DatabaseMetaData meta) throws SQLException {
ResultSet rs = meta.getProcedures(null, name, null);
ArrayList<DbProcedure> list = New.arrayList();
while (rs.next()) {
list.add(new DbProcedure(this, rs));
}
rs.close();
procedures = new DbProcedure[list.size()];
list.toArray(procedures);
if (procedures.length < MAX_PROCEDURES_LIST_COLUMNS) {
for (DbProcedure procedure : procedures) {
procedure.readParameters(meta);
}
}
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.web;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.util.New;
/**
* Contains meta data information about a table or a view.
* This class is used by the H2 Console.
*/
public class DbTableOrView {
/**
* The schema this table belongs to.
*/
final DbSchema schema;
/**
* The table name.
*/
final String name;
/**
* The quoted table name.
*/
final String quotedName;
/**
* True if this represents a view.
*/
final boolean isView;
/**
* The column list.
*/
DbColumn[] columns;
DbTableOrView(DbSchema schema, ResultSet rs) throws SQLException {
this.schema = schema;
name = rs.getString("TABLE_NAME");
String type = rs.getString("TABLE_TYPE");
isView = "VIEW".equals(type);
quotedName = schema.contents.quoteIdentifier(name);
}
/**
* Read the column for this table from the database meta data.
*
* @param meta the database meta data
*/
void readColumns(DatabaseMetaData meta) throws SQLException {
ResultSet rs = meta.getColumns(null, schema.name, name, null);
ArrayList<DbColumn> list = New.arrayList();
while (rs.next()) {
DbColumn column = new DbColumn(schema.contents, rs);
list.add(column);
}
rs.close();
columns = new DbColumn[list.size()];
list.toArray(columns);
}
}
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.bnf.context;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.util.New;
/**
* Contains meta data information about a table or a view.
* This class is used by the H2 Console.
*/
public class DbTableOrView {
/**
* The schema this table belongs to.
*/
private final DbSchema schema;
/**
* The table name.
*/
private final String name;
/**
* The quoted table name.
*/
private final String quotedName;
/**
* True if this represents a view.
*/
private final boolean isView;
/**
* The column list.
*/
private DbColumn[] columns;
public DbTableOrView(DbSchema schema, ResultSet rs) throws SQLException {
this.schema = schema;
name = rs.getString("TABLE_NAME");
String type = rs.getString("TABLE_TYPE");
isView = "VIEW".equals(type);
quotedName = schema.getContents().quoteIdentifier(name);
}
/**
* @return The schema this table belongs to.
*/
public DbSchema getSchema() {
return schema;
}
/**
* @return The column list.
*/
public DbColumn[] getColumns() {
return columns;
}
/**
* @return The table name.
*/
public String getName() {
return name;
}
/**
* @return True if this represents a view.
*/
public boolean isView() {
return isView;
}
/**
* @return The quoted table name.
*/
public String getQuotedName() {
return quotedName;
}
/**
* Read the column for this table from the database meta data.
*
* @param meta the database meta data
*/
public void readColumns(DatabaseMetaData meta) throws SQLException {
ResultSet rs = meta.getColumns(null, schema.name, name, null);
ArrayList<DbColumn> list = New.arrayList();
while (rs.next()) {
DbColumn column = new DbColumn(schema.getContents(), rs);
list.add(column);
}
rs.close();
columns = new DbColumn[list.size()];
list.toArray(columns);
}
}
......@@ -167,7 +167,7 @@ CREATE DOMAIN [ IF NOT EXISTS ] newDomainName AS dataType
Creates a new data type (domain)."
"Commands (DDL)","CREATE INDEX","
CREATE
{ [ UNIQUE ] [ HASH ] INDEX [ [ IF NOT EXISTS ] newIndexName ]
{ [ UNIQUE ] [ HASH ] [ SPATIAL] INDEX [ [ IF NOT EXISTS ] newIndexName ]
| PRIMARY KEY [ HASH ] }
ON tableName ( indexColumn [,...] )
","
......@@ -541,7 +541,7 @@ Default expressions are used if no explicit value was used when adding a row."
","
Comments can be used anywhere in a command and are ignored by the database."
"Other Grammar","Compare","
<> | <= | >= | = | < | > | !=
<> | <= | >= | = | < | > | != | &&
","
Comparison operator."
"Other Grammar","Condition","
......
......@@ -34,6 +34,10 @@ import java.util.Map;
import java.util.Properties;
import java.util.Random;
import org.h2.bnf.Bnf;
import org.h2.bnf.context.DbColumn;
import org.h2.bnf.context.DbContents;
import org.h2.bnf.context.DbSchema;
import org.h2.bnf.context.DbTableOrView;
import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
......@@ -469,20 +473,20 @@ public class WebApp {
private static int addColumns(boolean mainSchema, DbTableOrView table,
StringBuilder buff, int treeIndex, boolean showColumnTypes,
StringBuilder columnsBuffer) {
DbColumn[] columns = table.columns;
DbColumn[] columns = table.getColumns();
for (int i = 0; columns != null && i < columns.length; i++) {
DbColumn column = columns[i];
if (columnsBuffer.length() > 0) {
columnsBuffer.append(' ');
}
columnsBuffer.append(column.name);
String col = escapeIdentifier(column.name);
columnsBuffer.append(column.getName());
String col = escapeIdentifier(column.getName());
String level = mainSchema ? ", 1, 1" : ", 2, 2";
buff.append("setNode(" + treeIndex + level + ", 'column', '" + PageParser.escapeJavaScript(column.name)
buff.append("setNode(" + treeIndex + level + ", 'column', '" + PageParser.escapeJavaScript(column.getName())
+ "', 'javascript:ins(\\'" + col + "\\')');\n");
treeIndex++;
if (mainSchema && showColumnTypes) {
buff.append("setNode(" + treeIndex + ", 2, 2, 'type', '" + PageParser.escapeJavaScript(column.dataType)
buff.append("setNode(" + treeIndex + ", 2, 2, 'type', '" + PageParser.escapeJavaScript(column.getDataType())
+ "', null);\n");
treeIndex++;
}
......@@ -585,57 +589,57 @@ public class WebApp {
boolean showColumns = mainSchema || !schema.isSystem;
String indentation = ", " + level + ", " + (showColumns ? "1" : "2") + ", ";
String indentNode = ", " + (level + 1) + ", 2, ";
DbTableOrView[] tables = schema.tables;
DbTableOrView[] tables = schema.getTables();
if (tables == null) {
return treeIndex;
}
boolean isOracle = schema.contents.isOracle;
boolean isOracle = schema.getContents().isOracle();
boolean notManyTables = tables.length < DbSchema.MAX_TABLES_LIST_INDEXES;
for (DbTableOrView table : tables) {
if (table.isView) {
if (table.isView()) {
continue;
}
int tableId = treeIndex;
String tab = table.quotedName;
String tab = table.getQuotedName();
if (!mainSchema) {
tab = schema.quotedName + "." + tab;
}
tab = escapeIdentifier(tab);
buff.append("setNode(" + treeIndex + indentation + " 'table', '" + PageParser.escapeJavaScript(table.name)
buff.append("setNode(" + treeIndex + indentation + " 'table', '" + PageParser.escapeJavaScript(table.getName())
+ "', 'javascript:ins(\\'" + tab + "\\',true)');\n");
treeIndex++;
if (mainSchema || showColumns) {
StringBuilder columnsBuffer = new StringBuilder();
treeIndex = addColumns(mainSchema, table, buff, treeIndex, notManyTables, columnsBuffer);
if (!isOracle && notManyTables) {
treeIndex = addIndexes(mainSchema, meta, table.name, schema.name, buff, treeIndex);
treeIndex = addIndexes(mainSchema, meta, table.getName(), schema.name, buff, treeIndex);
}
buff.append("addTable('" + PageParser.escapeJavaScript(table.name) + "', '"
buff.append("addTable('" + PageParser.escapeJavaScript(table.getName()) + "', '"
+ PageParser.escapeJavaScript(columnsBuffer.toString()) + "', " + tableId + ");\n");
}
}
tables = schema.tables;
tables = schema.getTables();
for (DbTableOrView view : tables) {
if (!view.isView) {
if (!view.isView()) {
continue;
}
int tableId = treeIndex;
String tab = view.quotedName;
String tab = view.getQuotedName();
if (!mainSchema) {
tab = view.schema.quotedName + "." + tab;
tab = view.getSchema().quotedName + "." + tab;
}
tab = escapeIdentifier(tab);
buff.append("setNode(" + treeIndex + indentation + " 'view', '" + PageParser.escapeJavaScript(view.name)
buff.append("setNode(" + treeIndex + indentation + " 'view', '" + PageParser.escapeJavaScript(view.getName())
+ "', 'javascript:ins(\\'" + tab + "\\',true)');\n");
treeIndex++;
if (mainSchema) {
StringBuilder columnsBuffer = new StringBuilder();
treeIndex = addColumns(mainSchema, view, buff, treeIndex, notManyTables, columnsBuffer);
if (schema.contents.isH2) {
if (schema.getContents().isH2()) {
PreparedStatement prep = null;
try {
prep = conn.prepareStatement("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?");
prep.setString(1, view.name);
prep.setString(1, view.getName());
ResultSet rs = prep.executeQuery();
if (rs.next()) {
String sql = rs.getString("SQL");
......@@ -648,7 +652,7 @@ public class WebApp {
JdbcUtils.closeSilently(prep);
}
}
buff.append("addTable('" + PageParser.escapeJavaScript(view.name) + "', '"
buff.append("addTable('" + PageParser.escapeJavaScript(view.getName()) + "', '"
+ PageParser.escapeJavaScript(columnsBuffer.toString()) + "', " + tableId + ");\n");
}
}
......@@ -663,16 +667,16 @@ public class WebApp {
session.loadBnf();
Connection conn = session.getConnection();
DatabaseMetaData meta = session.getMetaData();
isH2 = contents.isH2;
isH2 = contents.isH2();
StringBuilder buff = new StringBuilder();
buff.append("setNode(0, 0, 0, 'database', '" + PageParser.escapeJavaScript((String) session.get("url"))
+ "', null);\n");
int treeIndex = 1;
DbSchema defaultSchema = contents.defaultSchema;
DbSchema defaultSchema = contents.getDefaultSchema();
treeIndex = addTablesAndViews(defaultSchema, true, buff, treeIndex);
DbSchema[] schemas = contents.schemas;
DbSchema[] schemas = contents.getSchemas();
for (DbSchema schema : schemas) {
if (schema == defaultSchema || schema == null) {
continue;
......@@ -983,7 +987,7 @@ public class WebApp {
result = buff.toString();
session.put("result", result);
} catch (Throwable e) {
session.put("result", getStackTrace(0, e, session.getContents().isH2));
session.put("result", getStackTrace(0, e, session.getContents().isH2()));
}
return "result.jsp";
}
......@@ -1034,7 +1038,7 @@ public class WebApp {
// cancel
}
} catch (Throwable e) {
result = "<br />" + getStackTrace(0, e, session.getContents().isH2);
result = "<br />" + getStackTrace(0, e, session.getContents().isH2());
error = formatAsError(e.getMessage());
}
String sql = "@edit " + (String) session.get("resultSetSQL");
......@@ -1212,7 +1216,7 @@ public class WebApp {
}
Statement stat;
DbContents contents = session.getContents();
if (forceEdit || (allowEdit && contents.isH2)) {
if (forceEdit || (allowEdit && contents.isH2())) {
stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
} else {
stat = conn.createStatement();
......@@ -1342,7 +1346,7 @@ public class WebApp {
return buff.toString();
} catch (Throwable e) {
// throwable: including OutOfMemoryError and so on
return getStackTrace(id, e, session.getContents().isH2);
return getStackTrace(id, e, session.getContents().isH2());
} finally {
session.executingStatement = null;
}
......@@ -1405,7 +1409,7 @@ public class WebApp {
prep.setInt(j + 1, i);
}
}
if (session.getContents().isSQLite) {
if (session.getContents().isSQLite()) {
// SQLite currently throws an exception on prep.execute()
prep.executeUpdate();
} else {
......@@ -1746,7 +1750,7 @@ public class WebApp {
}
ResultSetMetaData meta = rs.getMetaData();
int type = meta.getColumnType(columnIndex);
if (session.getContents().isH2) {
if (session.getContents().isH2()) {
rs.updateString(columnIndex, x);
return;
}
......
......@@ -17,6 +17,8 @@ import java.util.HashMap;
import java.util.Locale;
import org.h2.bnf.Bnf;
import org.h2.bnf.context.DbContents;
import org.h2.bnf.context.DbContextRule;
import org.h2.message.TraceSystem;
import org.h2.util.New;
......@@ -120,12 +122,14 @@ class WebSession {
DbContextRule tableRule = new DbContextRule(contents, DbContextRule.TABLE);
DbContextRule schemaRule = new DbContextRule(contents, DbContextRule.SCHEMA);
DbContextRule columnAliasRule = new DbContextRule(contents, DbContextRule.COLUMN_ALIAS);
DbContextRule procedureRule = new DbContextRule(contents, DbContextRule.PROCEDURE);
newBnf.updateTopic("column_name", columnRule);
newBnf.updateTopic("new_table_alias", newAliasRule);
newBnf.updateTopic("table_alias", aliasRule);
newBnf.updateTopic("column_alias", columnAliasRule);
newBnf.updateTopic("table_name", tableRule);
newBnf.updateTopic("schema_name", schemaRule);
newBnf.updateTopic("expression", procedureRule);
newBnf.linkStatements();
bnf = newBnf;
} catch (Exception e) {
......
......@@ -144,6 +144,7 @@ import org.h2.test.synth.sql.TestSynth;
import org.h2.test.synth.thread.TestMulti;
import org.h2.test.unit.TestAutoReconnect;
import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestBnf;
import org.h2.test.unit.TestCache;
import org.h2.test.unit.TestClearReferences;
import org.h2.test.unit.TestCollation;
......@@ -608,6 +609,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new TestAlterSchemaRename().runTest(this);
new TestAutoRecompile().runTest(this);
new TestBitField().runTest(this);
new TestBnf().runTest(this);
new TestBackup().runTest(this);
new TestBigDb().runTest(this);
new TestBigResult().runTest(this);
......
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import org.h2.bnf.Bnf;
import org.h2.bnf.context.DbContents;
import org.h2.bnf.context.DbContextRule;
import org.h2.bnf.context.DbProcedure;
import org.h2.bnf.context.DbSchema;
import org.h2.test.TestBase;
import java.sql.Connection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Test Bnf Sql parser
* @author Nicolas Fortin
*/
public class TestBnf extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public void test() throws Exception {
deleteDb("TestBnf");
Connection conn = getConnection("TestBnf");
try {
testProcedures(conn);
} finally {
conn.close();
}
}
private void testProcedures(Connection conn) throws Exception {
// Register a procedure and check if it is present in DbContents
conn.createStatement().execute("DROP ALIAS IF EXISTS CUSTOM_PRINT");
conn.createStatement().execute("CREATE ALIAS CUSTOM_PRINT AS $$ void print(String s) { System.out.println(s); } $$");
conn.createStatement().execute("DROP TABLE IF EXISTS TABLE_WITH_STRING_FIELD");
conn.createStatement().execute("CREATE TABLE TABLE_WITH_STRING_FIELD (STRING_FIELD VARCHAR(50), INT_FIELD integer)");
DbContents dbContents = new DbContents();
dbContents.readContents(conn.getMetaData());
DbSchema defaultSchema = dbContents.getDefaultSchema();
DbProcedure[] procedures = defaultSchema.getProcedures();
Set<String> procedureName = new HashSet<String>(procedures.length);
for(DbProcedure procedure : procedures) {
procedureName.add(procedure.getName());
}
assertTrue(procedureName.contains("CUSTOM_PRINT"));
// Test completion
Bnf bnf = Bnf.getInstance(null);
DbContextRule columnRule = new DbContextRule(dbContents, DbContextRule.COLUMN);
bnf.updateTopic("column_name", columnRule);
bnf.updateTopic("expression", new DbContextRule(dbContents, DbContextRule.PROCEDURE));
bnf.linkStatements();
// Test partial
Map<String, String> tokens = bnf.getNextTokenList("SELECT CUSTOM_PR");
assertTrue(tokens.values().contains("INT"));
// Test parameters
tokens = bnf.getNextTokenList("SELECT CUSTOM_PRINT(");
assertTrue(tokens.values().contains("STRING_FIELD"));
assertFalse(tokens.values().contains("INT_FIELD"));
// Test parameters with spaces
tokens = bnf.getNextTokenList("SELECT CUSTOM_PRINT ( ");
assertTrue(tokens.values().contains("STRING_FIELD"));
assertFalse(tokens.values().contains("INT_FIELD"));
// Test parameters with close bracket
tokens = bnf.getNextTokenList("SELECT CUSTOM_PRINT ( STRING_FIELD");
assertTrue(tokens.values().contains(")"));
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论