blob: d298a6780a92cb5f6f60014a0eea6da5305135d7 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.db.metadata.model.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import org.netbeans.modules.db.metadata.model.api.Catalog;
import org.netbeans.modules.db.metadata.model.api.Column;
import org.netbeans.modules.db.metadata.model.api.ForeignKey;
import org.netbeans.modules.db.metadata.model.api.ForeignKeyColumn;
import org.netbeans.modules.db.metadata.model.api.Index;
import org.netbeans.modules.db.metadata.model.api.Index.IndexType;
import org.netbeans.modules.db.metadata.model.api.IndexColumn;
import org.netbeans.modules.db.metadata.model.api.Ordering;
import org.netbeans.modules.db.metadata.model.api.Parameter;
import org.netbeans.modules.db.metadata.model.api.Parameter.Direction;
import org.netbeans.modules.db.metadata.model.api.PrimaryKey;
import org.netbeans.modules.db.metadata.model.api.Schema;
import org.netbeans.modules.db.metadata.model.api.Table;
import org.netbeans.modules.db.metadata.model.api.View;
import org.netbeans.modules.db.metadata.model.api.Procedure;
import org.netbeans.modules.db.metadata.model.api.SQLType;
import org.netbeans.modules.db.metadata.model.api.Tuple;
import org.netbeans.modules.db.metadata.model.jdbc.mysql.MySQLMetadata;
/**
* To override the defaults for the tests add properties to
* nbbuild/user.build.properties
*
* <pre><code>
* test-unit-sys-prop.mysql.host=...
* test-unit-sys-prop.mysql.port=...
* test-unit-sys-prop.mysql.database=...
* test-unit-sys-prop.mysql.user=...
* test-unit-sys-prop.mysql.password=...
* </code></pre>
*/
public class JDBCMetadataMySQLTest extends JDBCMetadataTestBase {
private JDBCMetadata metadata;
private String defaultCatalogName;
private Connection conn;
private Statement stmt;
private String mysqlHost;
private Integer mysqlPort;
private String mysqlUser;
private String mysqlPassword;
private String mysqlDatabase;
public JDBCMetadataMySQLTest(String name) {
super(name);
}
@Override
public void setUp() throws Exception {
mysqlHost = System.getProperty("mysql.host", "localhost");
mysqlPort = Integer.getInteger("mysql.port", 3306);
mysqlDatabase = System.getProperty("mysql.database", "test");
mysqlUser = System.getProperty("mysql.user", "test");
mysqlPassword = System.getProperty("mysql.password", "test");
clearWorkDir();
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://" + mysqlHost + ":" + mysqlPort, mysqlUser, mysqlPassword);
stmt = conn.createStatement();
stmt.executeUpdate("DROP DATABASE IF EXISTS test");
stmt.executeUpdate("DROP DATABASE IF EXISTS test2");
stmt.executeUpdate("CREATE DATABASE test");
stmt.executeUpdate("CREATE DATABASE test2");
conn = DriverManager.getConnection("jdbc:mysql://" + mysqlHost + ":" + mysqlPort + "/" + mysqlDatabase, mysqlUser, mysqlPassword);
stmt.executeUpdate("USE test");
stmt.executeUpdate("CREATE TABLE groucho (id INT NOT NULL, id2 INT NOT NULL, " +
"CONSTRAINT groucho_pk PRIMARY KEY (id2, id)) Engine=InnoDB");
// Create a table in another database with references, let's see if this works
stmt.executeUpdate("CREATE TABLE test2.harpo (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB");
stmt.executeUpdate("CREATE TABLE foo (" +
"id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, " +
"FOO_NAME VARCHAR(16), harpo_id INT NOT NULL, FOREIGN KEY(harpo_id) REFERENCES test2.harpo(id)) ENGINE=InnoDB");
stmt.executeUpdate("CREATE TABLE bar (" +
"`i+d` INT NOT NULL PRIMARY KEY, " +
"foo_id INT NOT NULL, " +
"bar_name VARCHAR(16), " +
"bar_digit DECIMAL(12,2) NOT NULL, " +
"FOREIGN KEY (foo_id) REFERENCES foo(id)) Engine=InnoDB");
stmt.executeUpdate("CREATE TABLE chico (id INT NOT NULL, groucho_id2 INT, groucho_id INT, foo_id INT, " +
"CONSTRAINT groucho_fk FOREIGN KEY (groucho_id2, groucho_id) REFERENCES groucho(id2, id), " +
"CONSTRAINT foo_fk FOREIGN KEY (foo_id) REFERENCES foo(id)) Engine=InnoDB");
stmt.executeUpdate("CREATE VIEW barview AS SELECT * FROM bar");
stmt.executeUpdate("CREATE UNIQUE INDEX groucho_index ON groucho(id2)");
stmt.executeUpdate("CREATE INDEX bar_name_index ON bar(bar_name, bar_digit)");
stmt.executeUpdate("CREATE UNIQUE INDEX bar_foo_index ON bar(foo_id)");
stmt.executeUpdate("CREATE PROCEDURE barproc(IN param1 INT, OUT result VARCHAR(255), INOUT param2 DECIMAL(5,2)) " +
"BEGIN SELECT * from bar; END");
stmt.executeUpdate("CREATE PROCEDURE fooproc(IN param1 INT) " +
"BEGIN SELECT * from foo; END");
metadata = new MySQLMetadata(conn, null);
defaultCatalogName = mysqlDatabase;
}
public void testBasic() throws Exception {
Collection<Catalog> catalogs = metadata.getCatalogs();
Catalog defaultCatalog = metadata.getDefaultCatalog();
assertEquals(defaultCatalogName, defaultCatalog.getName());
assertTrue(catalogs.contains(defaultCatalog));
Catalog informationSchema = metadata.getCatalog("information_schema");
assertFalse(informationSchema.isDefault());
Schema syntheticSchema = informationSchema.getSyntheticSchema();
assertNotNull(syntheticSchema);
assertFalse("Only the default catalog should have a default schema", syntheticSchema.isDefault());
Schema schema = metadata.getDefaultSchema();
assertTrue(schema.isSynthetic());
assertTrue(schema.isDefault());
assertSame(schema, defaultCatalog.getSyntheticSchema());
assertSame(defaultCatalog, schema.getParent());
Collection<Table> tables = schema.getTables();
assertNames(new HashSet<String>(Arrays.asList("foo", "bar", "groucho", "chico")), tables);
Table barTable = schema.getTable("bar");
assertTrue(tables.contains(barTable));
assertSame(schema, barTable.getParent());
checkColumns(barTable);
}
/**
* In MySQL it's possible to connect without specifying a database name, in which
* case there should be no default catalog and we should be able to get the full
* list of catalogs
*
* @throws java.lang.Exception
*/
public void testNoDatabaseSpecified() throws Exception {
Connection connection = DriverManager.getConnection("jdbc:mysql://" + mysqlHost + ":" + mysqlPort, mysqlUser, mysqlPassword);
JDBCMetadata md = new MySQLMetadata(connection, null);
Collection<Catalog> catalogs = md.getCatalogs();
assertNull(md.getDefaultCatalog().getName());
assertFalse(catalogs.contains(md.getDefaultCatalog()));
}
public void testSchemaRefresh() throws Exception {
Schema schema = metadata.getDefaultSchema();
Collection<Table> tables = schema.getTables();
assertNames(new HashSet<String>(Arrays.asList("foo", "bar", "groucho", "chico")), tables);
stmt.executeUpdate("CREATE TABLE testSchemaRefresh (" +
"id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, " +
"FOO_NAME VARCHAR(16))");
schema.refresh();
tables = schema.getTables();
assertNames(new HashSet<String>(Arrays.asList("foo", "bar", "groucho", "chico", "testSchemaRefresh")), tables);
}
public void testIndexes() {
Schema schema = metadata.getDefaultSchema();
Table table = schema.getTable("groucho");
Collection<Index> indexes = table.getIndexes();
assertNames(new HashSet<String>(Arrays.asList("groucho_index", "PRIMARY")), indexes);
Index index = table.getIndex("groucho_index");
assertEquals(index.getParent(), table);
assertTrue(index.isUnique());
assertEquals(IndexType.OTHER, index.getIndexType());
Collection<IndexColumn> columns = index.getColumns();
assertEquals(1, columns.size());
assertNames(new HashSet<String>(Arrays.asList("id2")), columns);
IndexColumn col = index.getColumn("id2");
assertNotNull(col);
assertEquals(index, col.getParent());
assertEquals(Ordering.ASCENDING, col.getOrdering());
assertEquals(1, col.getPosition());
index = table.getIndex("PRIMARY");
assertEquals(index.getParent(), table);
assertTrue(index.isUnique());
assertEquals(IndexType.OTHER, index.getIndexType());
columns = index.getColumns();
assertEquals(2, columns.size());
assertNames(new HashSet<String>(Arrays.asList("id2", "id")), columns);
col = index.getColumn("id2");
assertNotNull(col);
assertEquals(index, col.getParent());
assertEquals(Ordering.ASCENDING, col.getOrdering());
assertEquals(1, col.getPosition());
col = index.getColumn("id");
assertNotNull(col);
assertEquals(index, col.getParent());
assertEquals(Ordering.ASCENDING, col.getOrdering());
assertEquals(2, col.getPosition());
table = schema.getTable("bar");
indexes = table.getIndexes();
assertNames(new HashSet<String>(Arrays.asList("bar_name_index", "bar_foo_index", "PRIMARY")), indexes);
index = table.getIndex("bar_name_index");
assertEquals(index.getParent(), table);
assertFalse(index.isUnique());
columns = index.getColumns();
assertNames(new HashSet<String>(Arrays.asList("bar_name", "bar_digit")), columns);
col = index.getColumn("bar_name");
assertEquals(index, col.getParent());
assertEquals(Ordering.ASCENDING, col.getOrdering());
assertEquals(1, col.getPosition());
assertEquals(col.getColumn(), table.getColumn("bar_name"));
}
public void testForeignKey() throws Exception {
Schema schema = metadata.getDefaultSchema();
Table table = schema.getTable("chico");
Collection<ForeignKey> fkeys = table.getForeignKeys();
assertNames(new HashSet<String>(Arrays.asList("groucho_fk", "foo_fk")), fkeys);
for (ForeignKey key : fkeys) {
Collection<ForeignKeyColumn> cols = key.getColumns();
if ("groucho_fk".equals(key.getName())) {
assertNames(new HashSet<String>(Arrays.asList("groucho_id2", "groucho_id")), cols);
Table referredTable = schema.getTable("groucho");
checkForeignKeyColumn(key, referredTable, "groucho_id2", "id2", 1);
checkForeignKeyColumn(key, referredTable, "groucho_id", "id", 2);
} else {
assertNames(new HashSet<String>(Arrays.asList("foo_id")), cols);
checkForeignKeyColumn(key, schema.getTable("foo"), "foo_id", "id", 1);
}
}
table = schema.getTable("bar");
fkeys = table.getForeignKeys();
ForeignKey[] keys = table.getForeignKeys().toArray(new ForeignKey[0]);
assertEquals(1, keys.length);
ForeignKey key = keys[0];
// Don't know the name of this one, it's generated...
assertNotNull(key.getName());
checkForeignKeyColumn(key, schema.getTable("foo"), "foo_id", "id", 1);
}
public void testForeignKeyAcrossCatalogs() throws Exception {
Schema schema = metadata.getDefaultSchema();
Table table = schema.getTable("foo");
Collection<ForeignKey> fkeys = table.getForeignKeys();
assertEquals(1, fkeys.size());
ForeignKey key = fkeys.toArray(new ForeignKey[1])[0];
Table referredTable = metadata.getCatalog("test2").getSyntheticSchema().getTable("harpo");
checkForeignKeyColumn(key, referredTable, "harpo_id", "id", 1);
}
public void testPrimaryKey() {
Schema schema = metadata.getDefaultSchema();
Table grouchoTable = schema.getTable("groucho");
PrimaryKey key = grouchoTable.getPrimaryKey();
// In MySQL, it doesn't matter what identifier you use when you create
// the primary key, it is always named "PRIMARY"
assertEquals("PRIMARY", key.getName());
Column[] pkcols = key.getColumns().toArray(new Column[0]);
Column col1 = grouchoTable.getColumn("id");
Column col2 = grouchoTable.getColumn("id2");
assertEquals(pkcols.length, 2);
// In MySQL, it doesn't matter how you order the columns in your primary
// key definition, they are always ordered in the same order as the
// ordering in th table definition
assertEquals(col1, pkcols[0]);
assertEquals(col2, pkcols[1]);
}
public void testViews() throws Exception {
Schema schema = metadata.getDefaultSchema();
Collection<View> views = schema.getViews();
assertNames(new HashSet<String>(Arrays.asList("barview")), views);
View barView = schema.getView("barview");
assertTrue(views.contains(barView));
assertSame(schema, barView.getParent());
checkColumns(barView);
}
public void testProcedures() throws Exception {
Schema schema = metadata.getDefaultSchema();
Collection<Procedure> procs = schema.getProcedures();
assertNames(Arrays.asList("barproc", "fooproc"), procs);
Procedure barProc = schema.getProcedure("barproc");
Collection<Parameter> barParams = barProc.getParameters();
assertNames(Arrays.asList("param1", "result", "param2"), barParams);
// MySQL does not tell you what the result columns are - bummer
assertEquals(0, barProc.getColumns().size());
Procedure fooProc = schema.getProcedure("fooproc");
Collection<Parameter> fooParams = fooProc.getParameters();
assertNames(Arrays.asList("param1"), fooParams);
// MySQL does not tell you what the result columns are - bummer
assertEquals(0, barProc.getColumns().size());
Parameter param = barProc.getParameter("param1");
assertTrue(barParams.contains(param));
assertSame(barProc, param.getParent());
assertEquals("JDBCParameter[name=param1, type=INTEGER, length=0, precision=10, radix=10, scale=0, nullable=NULLABLE, direction=IN, position=1]", param.toString());
assertEquals(SQLType.INTEGER, param.getType());
assertEquals(0, param.getLength());
assertEquals(Direction.IN, param.getDirection());
assertEquals(10, param.getPrecision());
assertEquals(0, param.getScale());
assertEquals(10, param.getRadix());
param = barProc.getParameter("result");
assertTrue(barParams.contains(param));
assertSame(barProc, param.getParent());
assertEquals("JDBCParameter[name=result, type=VARCHAR, length=255, precision=0, radix=10, scale=0, nullable=NULLABLE, direction=OUT, position=2]", param.toString());
param = barProc.getParameter("param2");
assertTrue(barParams.contains(param));
assertSame(barProc, param.getParent());
assertEquals("JDBCParameter[name=param2, type=DECIMAL, length=0, precision=5, radix=10, scale=2, nullable=NULLABLE, direction=INOUT, position=3]", param.toString());
}
private void checkColumns(Tuple parent) {
Collection<Column> columns = parent.getColumns();
assertEquals(4, columns.size());
Column[] colarray = columns.toArray(new Column[4]);
Column col = colarray[0];
assertEquals("JDBCColumn[name=i+d, type=INTEGER, length=0, precision=10, radix=10, scale=0, nullable=NOT_NULLABLE, ordinal_position=1]", col.toString());
assertEquals("i+d", col.getName());
assertSame(parent, col.getParent());
assertEquals(SQLType.INTEGER, col.getType());
assertEquals(0, col.getLength());
assertEquals(10, col.getRadix());
assertEquals(10, col.getPrecision());
assertEquals(0, col.getScale());
assertEquals(1, col.getPosition());
col = colarray[1];
assertEquals("JDBCColumn[name=foo_id, type=INTEGER, length=0, precision=10, radix=10, scale=0, nullable=NOT_NULLABLE, ordinal_position=2]", col.toString());
col = colarray[2];
assertEquals("JDBCColumn[name=bar_name, type=VARCHAR, length=16, precision=0, radix=10, scale=0, nullable=NULLABLE, ordinal_position=3]", col.toString());
col = colarray[3];
assertEquals(12, col.getPrecision());
assertEquals(2, col.getScale());
assertEquals("JDBCColumn[name=bar_digit, type=DECIMAL, length=0, precision=12, radix=10, scale=2, nullable=NOT_NULLABLE, ordinal_position=4]", col.toString());
}
}