/* * ModeShape (http://www.modeshape.org) * * Licensed 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.modeshape.sequencer.ddl; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.modeshape.jcr.api.JcrConstants.NT_UNSTRUCTURED; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.CONSTRAINT_TYPE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.DATATYPE_LENGTH; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.DATATYPE_NAME; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.DATATYPE_PRECISION; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.DATATYPE_SCALE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.GRANTEE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.GRANT_PRIVILEGE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.PARSER_ID; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.PROPERTY_VALUE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_COLUMN_DEFINITION; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_COLUMN_REFERENCE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_CONSTRAINT_ATTRIBUTE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_CREATE_ASSERTION_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_CREATE_SCHEMA_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_CREATE_TABLE_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_CREATE_VIEW_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_FK_COLUMN_REFERENCE; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_GRANT_ON_TABLE_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_REVOKE_ON_TABLE_STATEMENT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_TABLE_CONSTRAINT; import static org.modeshape.sequencer.ddl.StandardDdlLexicon.TYPE_TABLE_REFERENCE; import java.util.ArrayList; import java.util.List; import javax.jcr.Node; import org.junit.Test; import org.modeshape.sequencer.ddl.dialect.oracle.OracleDdlParser; /** * Unit test for the behaviour of the ddl sequencer, when standard ddl files are sequenced * * @author Horia Chiorean */ public class StandardDdlSequencerTest extends AbstractDdlSequencerTest { @Test public void shouldSequenceCreateSchema() throws Exception { // CREATE SCHEMA hollywood // CREATE TABLE films (title varchar(255), release date, producerName varchar(255)) // CREATE VIEW winners AS // SELECT title, release FROM films WHERE producerName IS NOT NULL; Node statementsNode = sequenceDdl("ddl/create_schema.ddl"); assertThat(statementsNode.getNodes().getSize(), is(1l)); verifyPrimaryType(statementsNode, NT_UNSTRUCTURED); verifyProperty(statementsNode, PARSER_ID, "POSTGRES"); Node schemaNode = statementsNode.getNode("hollywood"); assertNotNull(schemaNode); verifyBaseProperties(schemaNode, NT_UNSTRUCTURED, "1", "1", "0", 2); verifyMixinType(schemaNode, TYPE_CREATE_SCHEMA_STATEMENT); verifyExpression(schemaNode, "CREATE SCHEMA hollywood"); Node filmsNode = schemaNode.getNode("films"); assertNotNull(filmsNode); verifyBaseProperties(filmsNode, NT_UNSTRUCTURED, "2", "5", "28", 3); verifyMixinType(filmsNode, TYPE_CREATE_TABLE_STATEMENT); verifyExpression(filmsNode, "CREATE TABLE films (title varchar(255), release date, producerName varchar(255))"); Node winnersNode = schemaNode.getNode("winners"); assertNotNull(winnersNode); verifyBaseProperties(winnersNode, NT_UNSTRUCTURED, "3", "5", "113", 0); verifyMixinType(winnersNode, TYPE_CREATE_VIEW_STATEMENT); verifyExpression(winnersNode, "CREATE VIEW winners AS SELECT title, release FROM films WHERE producerName IS NOT NULL;"); // Check Column Properties Node titleNode = filmsNode.getNode("title"); assertNotNull(titleNode); verifyPrimaryType(titleNode, NT_UNSTRUCTURED); verifyProperty(titleNode, DATATYPE_NAME, "VARCHAR"); verifyProperty(titleNode, DATATYPE_LENGTH, "255"); verifyMixinType(titleNode, TYPE_COLUMN_DEFINITION); Node releaseNode = filmsNode.getNode("release"); assertNotNull(releaseNode); verifyPrimaryType(releaseNode, NT_UNSTRUCTURED); verifyProperty(releaseNode, DATATYPE_NAME, "DATE"); verifyHasProperty(releaseNode, DATATYPE_LENGTH); verifyMixinType(titleNode, TYPE_COLUMN_DEFINITION); } @Test public void shouldSequenceCreateTable() throws Exception { // CREATE TABLE IDTABLE // ( // IDCONTEXT VARCHAR(20) NOT NULL PRIMARY KEY, // NEXTID NUMERIC // ); String targetExpression = "CREATE TABLE IDTABLE\n" + "(\n" + " IDCONTEXT VARCHAR(20) NOT NULL PRIMARY KEY,\n" + " NEXTID NUMERIC\n" + ");"; Node statementsNode = sequenceDdl("ddl/create_table.ddl"); assertThat(statementsNode.getNodes().getSize(), is(1l)); verifyPrimaryType(statementsNode, NT_UNSTRUCTURED); verifyProperty(statementsNode, PARSER_ID, "SQL92"); Node tableNode = statementsNode.getNode("IDTABLE"); assertNotNull(tableNode); verifyBaseProperties(tableNode, NT_UNSTRUCTURED, "1", "1", "0", 3); verifyMixinType(tableNode, TYPE_CREATE_TABLE_STATEMENT); verifyExpression(tableNode, targetExpression); // Check Column Properties Node idcontextNode = tableNode.getNode("IDCONTEXT"); assertNotNull(idcontextNode); verifyPrimaryType(idcontextNode, NT_UNSTRUCTURED); verifyProperty(idcontextNode, DATATYPE_NAME, "VARCHAR"); verifyProperty(idcontextNode, DATATYPE_LENGTH, "20"); verifyMixinType(idcontextNode, TYPE_COLUMN_DEFINITION); Node nextidNode = tableNode.getNode("NEXTID"); assertNotNull(nextidNode); verifyPrimaryType(nextidNode, NT_UNSTRUCTURED); verifyProperty(nextidNode, DATATYPE_NAME, "NUMERIC"); verifyProperty(nextidNode, DATATYPE_PRECISION, "0"); verifyProperty(nextidNode, DATATYPE_SCALE, "0"); verifyHasProperty(nextidNode, DATATYPE_LENGTH); verifyMixinType(nextidNode, TYPE_COLUMN_DEFINITION); Node pk_1_Node = tableNode.getNode("PK_1"); assertNotNull(pk_1_Node); verifyPrimaryType(pk_1_Node, NT_UNSTRUCTURED); verifyProperty(pk_1_Node, CONSTRAINT_TYPE, "PRIMARY KEY"); verifyMixinType(pk_1_Node, TYPE_TABLE_CONSTRAINT); // One column reference assertThat(pk_1_Node.getNodes().getSize(), is(1l)); Node idcontectRefNode = pk_1_Node.getNode("IDCONTEXT"); assertNotNull(idcontectRefNode); verifyPrimaryType(idcontectRefNode, NT_UNSTRUCTURED); verifyMixinType(idcontectRefNode, TYPE_COLUMN_REFERENCE); } @Test public void shouldGenerateNodeTypesForCreateTables() throws Exception { // Check one table // CREATE TABLE RT_MDLS // ( // MDL_UID NUMERIC(20) NOT NULL, // MDL_UUID VARCHAR(64) NOT NULL, // MDL_NM VARCHAR(255) NOT NULL, // MDL_VERSION VARCHAR(50), // DESCRIPTION VARCHAR(255), // MDL_URI VARCHAR(255), // MDL_TYPE NUMERIC(3), // IS_PHYSICAL CHAR(1) NOT NULL, // MULTI_SOURCED CHAR(1) DEFAULT '0', // VISIBILITY NUMERIC(3) // // ); Node statementsNode = sequenceDdl("ddl/createTables.ddl"); assertThat(statementsNode.getNodes().getSize(), is(20l)); verifyPrimaryType(statementsNode, NT_UNSTRUCTURED); verifyProperty(statementsNode, PARSER_ID, "SQL92"); Node tableNode = statementsNode.getNode("RT_MDLS"); assertNotNull(tableNode); verifyBaseProperties(tableNode, NT_UNSTRUCTURED, "81", "1", "2212", 10); verifyMixinType(tableNode, TYPE_CREATE_TABLE_STATEMENT); // Check Column Properties Node node_1 = tableNode.getNode("MDL_UUID"); assertNotNull(node_1); verifyPrimaryType(node_1, NT_UNSTRUCTURED); verifyProperty(node_1, DATATYPE_NAME, "VARCHAR"); verifyProperty(node_1, DATATYPE_LENGTH, "64"); verifyMixinType(node_1, TYPE_COLUMN_DEFINITION); Node node_2 = tableNode.getNode("MDL_TYPE"); assertNotNull(node_2); verifyPrimaryType(node_2, NT_UNSTRUCTURED); verifyProperty(node_2, DATATYPE_NAME, "NUMERIC"); verifyProperty(node_2, DATATYPE_PRECISION, "3"); verifyProperty(node_2, DATATYPE_SCALE, "0"); verifyHasProperty(node_2, DATATYPE_LENGTH); verifyMixinType(node_2, TYPE_COLUMN_DEFINITION); } @Test public void shouldSequenceStandardDdlFile() throws Exception { Node statementsNode = sequenceDdl("ddl/standard_test_statements.ddl"); assertEquals(44l, statementsNode.getNodes().getSize()); Node stmtNode = findNode(statementsNode, "assertNotNull", TYPE_CREATE_ASSERTION_STATEMENT); Node constraintAttribute = findNode(stmtNode, "CONSTRAINT_ATTRIBUTE", TYPE_CONSTRAINT_ATTRIBUTE); verifyProperty(constraintAttribute, PROPERTY_VALUE, "NOT DEFERRABLE"); stmtNode = findNode(statementsNode, "assertIsZero", TYPE_CREATE_ASSERTION_STATEMENT); constraintAttribute = findNode(stmtNode, "CONSTRAINT_ATTRIBUTE", TYPE_CONSTRAINT_ATTRIBUTE); verifyProperty(constraintAttribute, PROPERTY_VALUE, "INITIALLY DEFERRED"); Node tableNode = findNode(statementsNode, "employee", TYPE_CREATE_TABLE_STATEMENT); Node columnNode = findNode(tableNode, "empname", TYPE_COLUMN_DEFINITION); verifyProperty(columnNode, DATATYPE_NAME, "CHAR"); verifyProperty(columnNode, DATATYPE_LENGTH, 10); Node constraintNode = findNode(tableNode, "emp_fk1", TYPE_TABLE_CONSTRAINT); constraintAttribute = findNode(constraintNode, "CONSTRAINT_ATTRIBUTE", TYPE_CONSTRAINT_ATTRIBUTE); verifyProperty(constraintAttribute, PROPERTY_VALUE, "INITIALLY IMMEDIATE"); findNode(constraintNode, "deptno[1]", TYPE_COLUMN_REFERENCE); findNode(constraintNode, "dept", TYPE_TABLE_REFERENCE); findNode(constraintNode, "deptno[2]", TYPE_FK_COLUMN_REFERENCE); Node viewNode = findNode(statementsNode, "view_1", TYPE_CREATE_VIEW_STATEMENT); findNode(viewNode, "col1", TYPE_COLUMN_REFERENCE); tableNode = findNode(statementsNode, "table_5", TYPE_CREATE_TABLE_STATEMENT); assertEquals(18, tableNode.getNodes().getSize()); } @Test public void shouldSequenceStandardDdlGrantStatements() throws Exception { Node statementsNode = sequenceDdl("ddl/grant_test_statements.ddl"); assertEquals(4, statementsNode.getNodes().getSize()); // GRANT SELECT ON TABLE purchaseOrders TO maria,harry; Node grantNode = findNode(statementsNode, "purchaseOrders", TYPE_GRANT_ON_TABLE_STATEMENT); findNode(grantNode, "maria", GRANTEE); Node privNode = findNode(grantNode, "privilege", GRANT_PRIVILEGE); verifyProperty(privNode, TYPE, "SELECT"); // GRANT UPDATE, USAGE ON TABLE purchaseOrders FROM anita,zhi; grantNode = findNode(statementsNode, "billedOrders", TYPE_GRANT_ON_TABLE_STATEMENT); privNode = findNode(grantNode, "privilege", GRANT_PRIVILEGE); verifyProperty(privNode, TYPE, "UPDATE"); findNode(grantNode, "anita", GRANTEE); } @Test public void shouldSequenceStandardDdlRevokeStatements() throws Exception { Node statementsNode = sequenceDdl("ddl/revoke_test_statements.ddl"); assertEquals(4, statementsNode.getNodes().getSize()); // REVOKE SELECT ON TABLE purchaseOrders FROM maria,harry; Node revokeNode = findNode(statementsNode, "purchaseOrders", TYPE_REVOKE_ON_TABLE_STATEMENT); findNode(revokeNode, "maria", GRANTEE); Node privNode = findNode(revokeNode, "privilege", GRANT_PRIVILEGE); verifyProperty(privNode, TYPE, "SELECT"); // REVOKE UPDATE, USAGE ON TABLE purchaseOrders FROM anita,zhi CASCADE; revokeNode = findNode(statementsNode, "orderDetails", TYPE_REVOKE_ON_TABLE_STATEMENT); privNode = findNode(revokeNode, "privilege", GRANT_PRIVILEGE); verifyProperty(privNode, TYPE, "UPDATE"); findNode(revokeNode, "anita", GRANTEE); } protected String[] builtInGrammars() { List<String> builtInParserNames = new ArrayList<String>(); for (DdlParser parser : DdlParsers.BUILTIN_PARSERS) { builtInParserNames.add(parser.getId().toLowerCase()); } return builtInParserNames.toArray(new String[builtInParserNames.size()]); } @Test public void shouldHaveDefaultListOfGrammars() { DdlSequencer sequencer = new DdlSequencer(); String[] grammars = sequencer.getGrammars(); assertThat(grammars, is(builtInGrammars())); } @Test public void shouldCreateListOfDdlParserInstancesForDefaultListOfGrammars() { DdlSequencer sequencer = new DdlSequencer(); List<DdlParser> parsers = sequencer.getParserList(); assertThat(parsers, is(DdlParsers.BUILTIN_PARSERS)); } @Test public void shouldAllowSettingGrammarsWithEmptyArray() { DdlSequencer sequencer = new DdlSequencer(); sequencer.setGrammars(new String[] {}); assertThat(sequencer.getGrammars(), is(builtInGrammars())); } @Test public void shouldAllowSettingGrammarsWithNullArray() { DdlSequencer sequencer = new DdlSequencer(); sequencer.setGrammars(null); assertThat(sequencer.getGrammars(), is(builtInGrammars())); } @Test public void shouldAllowSettingGrammarsToNonEmptyArrayOfValidBuiltInGrammars() { DdlSequencer sequencer = new DdlSequencer(); String[] grammars = new String[] {new OracleDdlParser().getId(), new StandardDdlParser().getId()}; sequencer.setGrammars(grammars); assertThat(sequencer.getGrammars(), is(grammars)); } @Test public void shouldAllowSettingGrammarsToNonEmptyArrayOfValidAndNonExistantBuiltInGrammars() { DdlSequencer sequencer = new DdlSequencer(); String[] grammars = new String[] {new OracleDdlParser().getId(), new StandardDdlParser().getId(), "argle"}; sequencer.setGrammars(grammars); assertThat(sequencer.getGrammars(), is(grammars)); } @Test public void shouldCreateDdlParserInstancesForAllValidBuiltInGrammars() { DdlSequencer sequencer = new DdlSequencer(); String[] grammars = new String[] {new OracleDdlParser().getId(), new StandardDdlParser().getId(), "argle"}; sequencer.setGrammars(grammars); assertThat(sequencer.getGrammars(), is(grammars)); List<DdlParser> parsers = sequencer.getParserList(); assertThat(parsers.get(0), is((DdlParser)new OracleDdlParser())); assertThat(parsers.get(1), is((DdlParser)new StandardDdlParser())); assertThat(parsers.size(), is(2)); } @Test public void shouldCreateDdlParserInstancesForAllValidBuiltInGrammarsAndInstantiableParser() { DdlSequencer sequencer = new DdlSequencer(); String[] grammars = new String[] {new OracleDdlParser().getId(), new StandardDdlParser().getId(), ArgleDdlParser.class.getName()}; sequencer.setGrammars(grammars); assertThat(sequencer.getGrammars(), is(grammars)); List<DdlParser> parsers = sequencer.getParserList(); assertThat(parsers.get(0), is((DdlParser)new OracleDdlParser())); assertThat(parsers.get(1), is((DdlParser)new StandardDdlParser())); assertThat(parsers.get(2), is((DdlParser)new ArgleDdlParser())); assertThat(parsers.size(), is(3)); } protected static class ArgleDdlParser extends StandardDdlParser { @Override public String getId() { return "ARGLE"; } } }