public void testGetTypeInfo() throws Exception {
    String schema =
        "create table Table1 (Column1 varchar(200) not null, Column2 integer);"
            + "partition table Table1 on column Column1;"
            + "create procedure proc1 as select * from Table1 where Column1=?;"
            + "partition procedure proc1 on table Table1 column Column1;"
            + "create procedure proc2 as select * from Table1 where Column2=?;";

    VoltCompiler c = compileForDDLTest2(schema);
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
    VoltTable typeInfo = dut.getMetaData("typEINfo");
    System.out.println(typeInfo);
    // just do some minor sanity checks on size of table and that it contains the types
    // we expect
    HashMap<String, VoltType> expectedTypes = new HashMap<String, VoltType>();
    for (VoltType type : VoltType.values()) {
      if (type.isJdbcVisible()) {
        expectedTypes.put(type.toSQLString().toUpperCase(), type);
      }
    }
    assertEquals(expectedTypes.size(), typeInfo.getRowCount());
    assertEquals(18, typeInfo.getColumnCount());
    typeInfo.resetRowPosition();
    while (typeInfo.advanceRow()) {
      String gotName = typeInfo.getString("TYPE_NAME");
      VoltType expectedType = expectedTypes.remove(gotName);
      assertTrue(expectedType != null);
    }
    assertTrue(expectedTypes.isEmpty());
  }
  public void testGetClasses() throws Exception {
    String schema =
        "create table Table1 (Column1 varchar(200) not null, Column2 integer);"
            + "partition table Table1 on column Column1;"
            + "create procedure proc1 as select * from Table1 where Column1=?;"
            + "partition procedure proc1 on table Table1 column Column1;"
            + "create procedure proc2 as select * from Table1 where Column2=?;"
            + "import class org.voltdb_testprocs.fullddlfeatures.*;"
            + "create procedure from class org.voltdb_testprocs.fullddlfeatures.testImportProc;";

    VoltCompiler c = compileForDDLTest2(schema);
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
    VoltTable classes = dut.getMetaData("classes");
    System.out.println(classes);
    assertTrue(
        VoltTableTestHelpers.moveToMatchingRow(
            classes, "CLASS_NAME", "org.voltdb_testprocs.fullddlfeatures.testImportProc"));
    assertEquals(1, classes.get("VOLT_PROCEDURE", VoltType.INTEGER));
    assertEquals(1, classes.get("ACTIVE_PROC", VoltType.INTEGER));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingRow(
            classes,
            "CLASS_NAME",
            "org.voltdb_testprocs.fullddlfeatures.testCreateProcFromClassProc"));
    assertEquals(1, classes.get("VOLT_PROCEDURE", VoltType.INTEGER));
    assertEquals(0, classes.get("ACTIVE_PROC", VoltType.INTEGER));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingRow(
            classes, "CLASS_NAME", "org.voltdb_testprocs.fullddlfeatures.NoMeaningClass"));
    assertEquals(0, classes.get("VOLT_PROCEDURE", VoltType.INTEGER));
    assertEquals(0, classes.get("ACTIVE_PROC", VoltType.INTEGER));
  }
  public void testGetPrimaryKeys() throws Exception {
    String schema =
        "create table Table1 (Column1 smallint not null, constraint primary1 primary key (Column1));"
            + "partition table Table1 on column Column1;"
            + "create table Table2 (Column2 smallint not null, Column3 smallint not null, Column4 smallint not null, "
            + "  constraint primary2 primary key (Column2, Column3, Column4));"
            + "create procedure sample as select * from Table1;";

    VoltCompiler c = compileForDDLTest2(schema);
    System.out.println(c.getCatalog().serialize());
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
    VoltTable pkeys = dut.getMetaData("PrimaryKeys");
    System.out.println(pkeys);
    assertEquals(6, pkeys.getColumnCount());
    assertEquals(4, pkeys.getRowCount());
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(pkeys, "COLUMN_NAME", "Column1"));
    assertEquals("TABLE1", pkeys.get("TABLE_NAME", VoltType.STRING));
    assertEquals((short) 1, pkeys.get("KEY_SEQ", VoltType.SMALLINT));
    assertEquals("PRIMARY1", pkeys.get("PK_NAME", VoltType.STRING));
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(pkeys, "COLUMN_NAME", "Column2"));
    assertEquals("TABLE2", pkeys.get("TABLE_NAME", VoltType.STRING));
    assertEquals((short) 1, pkeys.get("KEY_SEQ", VoltType.SMALLINT));
    assertEquals("PRIMARY2", pkeys.get("PK_NAME", VoltType.STRING));
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(pkeys, "COLUMN_NAME", "Column3"));
    assertEquals("TABLE2", pkeys.get("TABLE_NAME", VoltType.STRING));
    assertEquals((short) 2, pkeys.get("KEY_SEQ", VoltType.SMALLINT));
    assertEquals("PRIMARY2", pkeys.get("PK_NAME", VoltType.STRING));
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(pkeys, "COLUMN_NAME", "Column4"));
    assertEquals("TABLE2", pkeys.get("TABLE_NAME", VoltType.STRING));
    assertEquals((short) 3, pkeys.get("KEY_SEQ", VoltType.SMALLINT));
    assertEquals("PRIMARY2", pkeys.get("PK_NAME", VoltType.STRING));
  }
  public void testGetProcedureColumns() throws Exception {
    String schema =
        "create table Table1 (Column1 varchar(200) not null, Column2 integer);"
            + "partition table Table1 on column Column1;"
            + "create procedure proc1 as select * from Table1 where Column1=?;"
            + "partition procedure proc1 on table Table1 column Column1;"
            + "create procedure proc2 as select * from Table1 where Column2=?;";

    VoltCompiler c = compileForDDLTest2(schema);
    System.out.println(c.getCatalog().serialize());
    DefaultProcedureManager defaultProcs = new DefaultProcedureManager(c.getCatalogDatabase());
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(
            c.getCatalog(), defaultProcs, new InMemoryJarfile(testout_jar));
    VoltTable params = dut.getMetaData("ProcedureColumns");
    System.out.println(params);
    assertEquals(20, params.getColumnCount());
    assertEquals(4, params.getRowCount()); // 2 real and 2 crud inserts
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(params, "PROCEDURE_NAME", "proc1"));
    assertEquals("param0", params.get("COLUMN_NAME", VoltType.STRING));
    assertEquals(VoltType.MAX_VALUE_LENGTH, params.get("PRECISION", VoltType.INTEGER));
    assertEquals(VoltType.MAX_VALUE_LENGTH, params.get("LENGTH", VoltType.INTEGER));
    assertEquals(VoltType.MAX_VALUE_LENGTH, params.get("CHAR_OCTET_LENGTH", VoltType.INTEGER));
    assertEquals("PARTITION_PARAMETER", params.get("REMARKS", VoltType.STRING));
    assertTrue(VoltTableTestHelpers.moveToMatchingRow(params, "PROCEDURE_NAME", "proc2"));
    assertEquals("param0", params.get("COLUMN_NAME", VoltType.STRING));
    assertEquals(
        VoltType.INTEGER.getLengthInBytesForFixedTypes() * 8 - 1,
        params.get("PRECISION", VoltType.INTEGER));
    assertEquals(
        VoltType.INTEGER.getLengthInBytesForFixedTypes(), params.get("LENGTH", VoltType.INTEGER));
    assertWithNullCheck(null, params.get("CHAR_OCTET_LENGTH", VoltType.INTEGER), params);
    assertWithNullCheck(null, params.get("REMARKS", VoltType.STRING), params);
  }
Beispiel #5
0
  public static void main(final String[] args) {
    // Parse arguments
    if (args.length < 5 || args.length > 6) {
      System.err.println(
          "VoltCompiler [project file] [hosts] [sites per host] [leader IP] [output JAR] [k-safety factor (optional/future)] ");
      System.exit(1);
    }
    final String projectPath = args[0];
    final int hostCount = Integer.parseInt(args[1]);
    final int siteCount = Integer.parseInt(args[2]);
    final String leaderAddress = args[3];
    final String outputJar = args[4];
    int k_factor = 0;
    if (args.length == 6) {
      k_factor = Integer.parseInt(args[5]);
    }

    // Compile and exit with error code if we failed
    final ClusterConfig cluster_config =
        new ClusterConfig(hostCount, siteCount, k_factor, leaderAddress);
    final VoltCompiler compiler = new VoltCompiler();
    final boolean success =
        compiler.compile(projectPath, cluster_config, outputJar, System.out, null);
    if (!success) {
      System.exit(-1);
    }
  }
 private VoltCompiler compileForDDLTest2(String ddl) throws Exception {
   String ddlPath = getPathForSchema(ddl);
   final VoltCompiler compiler = new VoltCompiler();
   boolean success = compiler.compileFromDDL(testout_jar, ddlPath);
   assertTrue("Catalog compile failed!", success);
   return compiler;
 }
Beispiel #7
0
 public boolean compile(
     final String jarPath,
     final int sitesPerHost,
     final int hostCount,
     final int replication,
     final String leaderAddress) {
   VoltCompiler compiler = new VoltCompiler();
   if (m_replicatedSecondaryIndexesEnabled) {
     compiler.enableVerticalPartitionOptimizations();
   }
   return compile(compiler, jarPath, sitesPerHost, hostCount, replication, leaderAddress);
 }
 public void testGetTables() throws Exception {
   String schema =
       "create table Table1 (Column1 varchar(10) not null, Column2 integer);"
           + "partition table Table1 on column Column1;"
           + "create table Table2 (Column1 integer);"
           + "create view View1 (Column1, num) as select Column1, count(*) from Table1 group by Column1;"
           + "create view View2 (Column2, num) as select Column2, count(*) from Table1 group by Column2;"
           + "create table Export1 (Column1 integer);"
           + "export table Export1;"
           + "create table Export2 (Column1 integer);"
           + "export table Export2 to stream foo;"
           + "create procedure sample as select * from Table1;";
   VoltCompiler c = compileForDDLTest2(schema);
   System.out.println(c.getCatalog().serialize());
   JdbcDatabaseMetaDataGenerator dut =
       new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
   VoltTable tables = dut.getMetaData("tables");
   System.out.println(tables);
   assertEquals(10, tables.getColumnCount());
   assertEquals(6, tables.getRowCount());
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "Table1"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("TABLE"));
   assertTrue(tables.get("REMARKS", VoltType.STRING).equals("{\"partitionColumn\":\"COLUMN1\"}"));
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "Table2"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("TABLE"));
   assertEquals(null, tables.get("REMARKS", VoltType.STRING));
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "View1"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("VIEW"));
   assertTrue(
       tables
           .get("REMARKS", VoltType.STRING)
           .equals(
               new JSONObject("{\"partitionColumn\":\"COLUMN1\",\"sourceTable\":\"TABLE1\"}")
                   .toString()));
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "View2"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("VIEW"));
   assertTrue(
       tables
           .get("REMARKS", VoltType.STRING)
           .equals(
               new JSONObject("{\"partitionColumn\":\"COLUMN1\",\"sourceTable\":\"TABLE1\"}")
                   .toString()));
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "Export1"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("EXPORT"));
   assertTrue(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "Export2"));
   assertTrue(tables.get("TABLE_TYPE", VoltType.STRING).equals("EXPORT"));
   assertFalse(VoltTableTestHelpers.moveToMatchingRow(tables, "TABLE_NAME", "NotATable"));
 }
Beispiel #9
0
 public Catalog compile(
     final String jarPath,
     final int sitesPerHost,
     final int hostCount,
     final int replication,
     final String voltRoot) {
   VoltCompiler compiler = new VoltCompiler();
   if (compile(
       compiler,
       jarPath,
       voltRoot,
       new DeploymentInfo(hostCount, sitesPerHost, replication, false, 0, false),
       m_ppdEnabled,
       m_snapshotPath,
       m_ppdPrefix)) {
     return compiler.getCatalog();
   } else {
     return null;
   }
 }
Beispiel #10
0
  static void compileSingleStmtProcedure(
      VoltCompiler compiler,
      HSQLInterface hsql,
      DatabaseEstimates estimates,
      Catalog catalog,
      Database db,
      ProcedureDescriptor procedureDescriptor)
      throws VoltCompiler.VoltCompilerException {
    final String className = procedureDescriptor.m_className;
    if (className.indexOf('@') != -1) {
      throw compiler.new VoltCompilerException("User procedure names can't contain \"@\".");
    }

    // get the short name of the class (no package if a user procedure)
    // use the Table.<builtin> name (allowing the period) if builtin.
    String shortName = className;
    if (procedureDescriptor.m_builtInStmt == false) {
      String[] parts = className.split("\\.");
      shortName = parts[parts.length - 1];
    }

    // add an entry to the catalog (using the full className)
    final Procedure procedure = db.getProcedures().add(shortName);
    for (String groupName : procedureDescriptor.m_authGroups) {
      final Group group = db.getGroups().get(groupName);
      if (group == null) {
        throw compiler
        .new VoltCompilerException(
            "Procedure "
                + className
                + " allows access by a role "
                + groupName
                + " that does not exist");
      }
      final GroupRef groupRef = procedure.getAuthgroups().add(groupName);
      groupRef.setGroup(group);
    }
    procedure.setClassname(className);
    // sysprocs don't use the procedure compiler
    procedure.setSystemproc(false);
    procedure.setDefaultproc(procedureDescriptor.m_builtInStmt);
    procedure.setHasjava(false);

    // get the annotation
    // first try to get one that has been passed from the compiler
    ProcInfoData info = compiler.getProcInfoOverride(shortName);
    // then check for the usual one in the class itself
    // and create a ProcInfo.Data instance for it
    if (info == null) {
      info = new ProcInfoData();
      if (procedureDescriptor.m_partitionString != null) {
        info.partitionInfo = procedureDescriptor.m_partitionString;
        info.singlePartition = true;
      }
    }
    assert (info != null);

    // ADD THE STATEMENT

    // add the statement to the catalog
    Statement catalogStmt = procedure.getStatements().add(VoltDB.ANON_STMT_NAME);

    // compile the statement
    StatementPartitioning partitioning =
        info.singlePartition ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
    // default to FASTER detmode because stmt procs can't feed read output into writes
    StatementCompiler.compileFromSqlTextAndUpdateCatalog(
        compiler,
        hsql,
        catalog,
        db,
        estimates,
        catalogStmt,
        procedureDescriptor.m_singleStmt,
        procedureDescriptor.m_joinOrder,
        DeterminismMode.FASTER,
        partitioning);

    // if the single stmt is not read only, then the proc is not read only
    boolean procHasWriteStmts = (catalogStmt.getReadonly() == false);

    // set the read onlyness of a proc
    procedure.setReadonly(procHasWriteStmts == false);

    int seqs = catalogStmt.getSeqscancount();
    procedure.setHasseqscans(seqs > 0);

    // set procedure parameter types
    CatalogMap<ProcParameter> params = procedure.getParameters();
    CatalogMap<StmtParameter> stmtParams = catalogStmt.getParameters();

    // set the procedure parameter types from the statement parameter types
    int paramCount = 0;
    for (StmtParameter stmtParam : CatalogUtil.getSortedCatalogItems(stmtParams, "index")) {
      // name each parameter "param1", "param2", etc...
      ProcParameter procParam = params.add("param" + String.valueOf(paramCount));
      procParam.setIndex(stmtParam.getIndex());
      procParam.setIsarray(stmtParam.getIsarray());
      procParam.setType(stmtParam.getJavatype());
      paramCount++;
    }

    // parse the procinfo
    procedure.setSinglepartition(info.singlePartition);
    if (info.singlePartition) {
      parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
      if (procedure.getPartitionparameter() >= params.size()) {
        String msg =
            "PartitionInfo parameter not a valid parameter for procedure: "
                + procedure.getClassname();
        throw compiler.new VoltCompilerException(msg);
      }
      // TODO: The planner does not currently validate that a single-statement plan declared as
      // single-partition correctly uses
      // the designated parameter as a partitioning filter, maybe some day.
      // In theory, the PartitioningForStatement would confirm the use of (only) a parameter as a
      // partition key --
      // or if the partition key was determined to be some other hard-coded constant (expression?)
      // it might display a warning
      // message that the passed parameter is assumed to be equal to that constant (expression).
    } else {
      if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
        AbstractExpression statementPartitionExpression =
            partitioning.singlePartitioningExpressionForReport();
        if (statementPartitionExpression != null) {
          // The planner has uncovered an overlooked opportunity to run the statement SP.
          String msg = null;
          if (statementPartitionExpression instanceof ParameterValueExpression) {
            msg =
                "This procedure would benefit from setting the attribute 'partitioninfo="
                    + partitioning.getFullColumnName()
                    + ":"
                    + ((ParameterValueExpression) statementPartitionExpression).getParameterIndex()
                    + "'";
          } else {
            String valueDescription = null;
            Object partitionValue = partitioning.getInferredPartitioningValue();
            if (partitionValue == null) {
              // Statement partitioned on a runtime constant. This is likely to be cryptic, but
              // hopefully gets the idea across.
              valueDescription = "of " + statementPartitionExpression.explain("");
            } else {
              valueDescription =
                  partitionValue.toString(); // A simple constant value COULD have been a parameter.
            }
            msg =
                "This procedure would benefit from adding a parameter to be passed the value "
                    + valueDescription
                    + " and setting the attribute 'partitioninfo="
                    + partitioning.getFullColumnName()
                    + ":"
                    + paramCount
                    + "'";
          }
          compiler.addWarn(msg);
        }
      }
    }
  }
Beispiel #11
0
  static void compileJavaProcedure(
      VoltCompiler compiler,
      HSQLInterface hsql,
      DatabaseEstimates estimates,
      Catalog catalog,
      Database db,
      ProcedureDescriptor procedureDescriptor,
      InMemoryJarfile jarOutput)
      throws VoltCompiler.VoltCompilerException {

    final String className = procedureDescriptor.m_className;
    final Language lang = procedureDescriptor.m_language;

    // Load the class given the class name
    Class<?> procClass = procedureDescriptor.m_class;

    // get the short name of the class (no package)
    String shortName = deriveShortProcedureName(className);

    // add an entry to the catalog
    final Procedure procedure = db.getProcedures().add(shortName);
    for (String groupName : procedureDescriptor.m_authGroups) {
      final Group group = db.getGroups().get(groupName);
      if (group == null) {
        throw compiler
        .new VoltCompilerException(
            "Procedure "
                + className
                + " allows access by a role "
                + groupName
                + " that does not exist");
      }
      final GroupRef groupRef = procedure.getAuthgroups().add(groupName);
      groupRef.setGroup(group);
    }
    procedure.setClassname(className);
    // sysprocs don't use the procedure compiler
    procedure.setSystemproc(false);
    procedure.setDefaultproc(procedureDescriptor.m_builtInStmt);
    procedure.setHasjava(true);
    procedure.setLanguage(lang.name());
    ProcedureAnnotation pa = (ProcedureAnnotation) procedure.getAnnotation();
    if (pa == null) {
      pa = new ProcedureAnnotation();
      procedure.setAnnotation(pa);
    }
    if (procedureDescriptor.m_scriptImpl != null) {
      // This is a Groovy or other Java derived procedure and we need to add an annotation with
      // the script to the Procedure element in the Catalog
      pa.scriptImpl = procedureDescriptor.m_scriptImpl;
    }

    // get the annotation
    // first try to get one that has been passed from the compiler
    ProcInfoData info = compiler.getProcInfoOverride(shortName);
    // check if partition info was set in ddl
    ProcInfoData ddlInfo = null;
    if (procedureDescriptor.m_partitionString != null
        && !procedureDescriptor.m_partitionString.trim().isEmpty()) {
      ddlInfo = new ProcInfoData();
      ddlInfo.partitionInfo = procedureDescriptor.m_partitionString;
      ddlInfo.singlePartition = true;
    }
    // then check for the usual one in the class itself
    // and create a ProcInfo.Data instance for it
    if (info == null) {
      info = new ProcInfoData();
      ProcInfo annotationInfo = procClass.getAnnotation(ProcInfo.class);
      // error out if partition info is present in both ddl and annotation
      if (annotationInfo != null) {
        if (ddlInfo != null) {
          String msg = "Procedure: " + shortName + " has partition properties defined both in ";
          msg += "class \"" + className + "\" and in the schema defintion file(s)";
          throw compiler.new VoltCompilerException(msg);
        }
        // Prevent AutoGenerated DDL from including PARTITION PROCEDURE for this procedure.
        pa.classAnnotated = true;
        info.partitionInfo = annotationInfo.partitionInfo();
        info.singlePartition = annotationInfo.singlePartition();
      } else if (ddlInfo != null) {
        info = ddlInfo;
      }
    } else {
      pa.classAnnotated = true;
    }
    assert (info != null);

    // make sure multi-partition implies no partitoning info
    if (info.singlePartition == false) {
      if ((info.partitionInfo != null) && (info.partitionInfo.length() > 0)) {
        String msg = "Procedure: " + shortName + " is annotated as multi-partition";
        msg += " but partitionInfo has non-empty value: \"" + info.partitionInfo + "\"";
        throw compiler.new VoltCompilerException(msg);
      }
    }

    // track if there are any writer statements and/or sequential scans and/or an overlooked common
    // partitioning parameter
    boolean procHasWriteStmts = false;
    boolean procHasSeqScans = false;
    // procWantsCommonPartitioning == true but commonPartitionExpression == null signifies a proc
    // for which the planner was requested to attempt to find an SP plan, but that was not possible
    // -- it had a replicated write or it had one or more partitioned reads that were not all
    // filtered by the same partition key value -- so it was planned as an MP proc.
    boolean procWantsCommonPartitioning = true;
    AbstractExpression commonPartitionExpression = null;
    String exampleSPstatement = null;
    Object exampleSPvalue = null;

    // iterate through the fields and get valid sql statements
    Map<String, Object> fields = lang.accept(procedureIntrospector(compiler), procClass);

    // determine if proc is read or read-write by checking if the proc contains any write sql stmts
    boolean readWrite = false;
    for (Object field : fields.values()) {
      if (!(field instanceof SQLStmt)) continue;
      SQLStmt stmt = (SQLStmt) field;
      QueryType qtype = QueryType.getFromSQL(stmt.getText());
      if (!qtype.isReadOnly()) {
        readWrite = true;
        break;
      }
    }

    // default to FASTER determinism mode, which may favor non-deterministic plans
    // but if it's a read-write proc, use a SAFER planning mode wrt determinism.
    final DeterminismMode detMode = readWrite ? DeterminismMode.SAFER : DeterminismMode.FASTER;

    for (Entry<String, Object> entry : fields.entrySet()) {
      if (!(entry.getValue() instanceof SQLStmt)) continue;

      String stmtName = entry.getKey();
      SQLStmt stmt = (SQLStmt) entry.getValue();

      // add the statement to the catalog
      Statement catalogStmt = procedure.getStatements().add(stmtName);

      // compile the statement
      StatementPartitioning partitioning =
          info.singlePartition ? StatementPartitioning.forceSP() : StatementPartitioning.forceMP();
      boolean cacheHit =
          StatementCompiler.compileFromSqlTextAndUpdateCatalog(
              compiler,
              hsql,
              catalog,
              db,
              estimates,
              catalogStmt,
              stmt.getText(),
              stmt.getJoinOrder(),
              detMode,
              partitioning);

      // if this was a cache hit or specified single, don't worry about figuring out more
      // partitioning
      if (partitioning.wasSpecifiedAsSingle() || cacheHit) {
        procWantsCommonPartitioning = false; // Don't try to infer what's already been asserted.
        // The planner does not currently attempt to second-guess a plan declared as
        // single-partition, maybe some day.
        // In theory, the PartitioningForStatement would confirm the use of (only) a parameter as a
        // partition key --
        // or if the partition key was determined to be some other constant (expression?) it might
        // display an informational
        // message that the passed parameter is assumed to be equal to the hard-coded partition key
        // constant (expression).

        // Validate any inferred statement partitioning given the statement's possible usage, until
        // a contradiction is found.
      } else if (procWantsCommonPartitioning) {
        // Only consider statements that are capable of running SP with a partitioning parameter
        // that does not seem to
        // conflict with the partitioning of prior statements.
        if (partitioning.getCountOfIndependentlyPartitionedTables() == 1) {
          AbstractExpression statementPartitionExpression =
              partitioning.singlePartitioningExpressionForReport();
          if (statementPartitionExpression != null) {
            if (commonPartitionExpression == null) {
              commonPartitionExpression = statementPartitionExpression;
              exampleSPstatement = stmt.getText();
              exampleSPvalue = partitioning.getInferredPartitioningValue();
            } else if (commonPartitionExpression.equals(statementPartitionExpression)
                || (statementPartitionExpression instanceof ParameterValueExpression
                    && commonPartitionExpression instanceof ParameterValueExpression)) {
              // Any constant used for partitioning would have to be the same for all statements,
              // but
              // any statement parameter used for partitioning MIGHT come from the same proc
              // parameter as
              // any other statement's parameter used for partitioning.
            } else {
              procWantsCommonPartitioning =
                  false; // appears to be different partitioning for different statements
            }
          } else {
            // There is a statement with a partitioned table whose partitioning column is
            // not equality filtered with a constant or param. Abandon all hope.
            procWantsCommonPartitioning = false;
          }

          // Usually, replicated-only statements in a mix with others have no effect on the MP/SP
          // decision
        } else if (partitioning.getCountOfPartitionedTables() == 0) {
          // but SP is strictly forbidden for DML, to maintain the consistency of the replicated
          // data.
          if (partitioning.getIsReplicatedTableDML()) {
            procWantsCommonPartitioning = false;
          }

        } else {
          // There is a statement with a partitioned table whose partitioning column is
          // not equality filtered with a constant or param. Abandon all hope.
          procWantsCommonPartitioning = false;
        }
      }

      // if a single stmt is not read only, then the proc is not read only
      if (catalogStmt.getReadonly() == false) {
        procHasWriteStmts = true;
      }

      if (catalogStmt.getSeqscancount() > 0) {
        procHasSeqScans = true;
      }
    }

    // MIGHT the planner have uncovered an overlooked opportunity to run all statements SP?
    if (procWantsCommonPartitioning && (commonPartitionExpression != null)) {
      String msg = null;
      if (commonPartitionExpression instanceof ParameterValueExpression) {
        msg =
            "This procedure might benefit from an @ProcInfo annotation designating parameter "
                + ((ParameterValueExpression) commonPartitionExpression).getParameterIndex()
                + " of statement '"
                + exampleSPstatement
                + "'";
      } else {
        String valueDescription = null;
        if (exampleSPvalue == null) {
          // Statements partitioned on a runtime constant. This is likely to be cryptic, but
          // hopefully gets the idea across.
          valueDescription = "of " + commonPartitionExpression.explain("");
        } else {
          valueDescription =
              exampleSPvalue.toString(); // A simple constant value COULD have been a parameter.
        }
        msg =
            "This procedure might benefit from an @ProcInfo annotation referencing an added parameter passed the value "
                + valueDescription;
      }
      compiler.addInfo(msg);
    }

    // set the read onlyness of a proc
    procedure.setReadonly(procHasWriteStmts == false);

    procedure.setHasseqscans(procHasSeqScans);

    for (Statement catalogStmt : procedure.getStatements()) {
      if (catalogStmt.getIscontentdeterministic() == false) {
        String potentialErrMsg =
            "Procedure "
                + shortName
                + " has a statement with a non-deterministic result - statement: \""
                + catalogStmt.getSqltext()
                + "\" , reason: "
                + catalogStmt.getNondeterminismdetail();
        // throw compiler.new VoltCompilerException(potentialErrMsg);
        compiler.addWarn(potentialErrMsg);
      } else if (catalogStmt.getIsorderdeterministic() == false) {
        String warnMsg;
        if (procHasWriteStmts) {
          String rwPotentialErrMsg =
              "Procedure "
                  + shortName
                  + " is RW and has a statement whose result has a non-deterministic ordering - statement: \""
                  + catalogStmt.getSqltext()
                  + "\", reason: "
                  + catalogStmt.getNondeterminismdetail();
          // throw compiler.new VoltCompilerException(rwPotentialErrMsg);
          warnMsg = rwPotentialErrMsg;
        } else {
          warnMsg =
              "Procedure "
                  + shortName
                  + " has a statement with a non-deterministic result - statement: \""
                  + catalogStmt.getSqltext()
                  + "\", reason: "
                  + catalogStmt.getNondeterminismdetail();
        }
        compiler.addWarn(warnMsg);
      }
    }

    // set procedure parameter types
    CatalogMap<ProcParameter> params = procedure.getParameters();
    Class<?>[] paramTypes = lang.accept(procedureEntryPointParametersTypeExtractor, fields);
    for (int i = 0; i < paramTypes.length; i++) {
      Class<?> cls = paramTypes[i];
      ProcParameter param = params.add(String.valueOf(i));
      param.setIndex(i);

      // handle the case where the param is an array
      if (cls.isArray()) {
        param.setIsarray(true);
        cls = cls.getComponentType();
      } else param.setIsarray(false);

      // boxed types are not supported parameters at this time
      if ((cls == Long.class)
          || (cls == Integer.class)
          || (cls == Short.class)
          || (cls == Byte.class)
          || (cls == Double.class)
          || (cls == Character.class)
          || (cls == Boolean.class)) {
        String msg = "Procedure: " + shortName + " has a parameter with a boxed type: ";
        msg += cls.getSimpleName();
        msg +=
            ". Replace this parameter with the corresponding primitive type and the procedure may compile.";
        throw compiler.new VoltCompilerException(msg);
      } else if ((cls == Float.class) || (cls == float.class)) {
        String msg = "Procedure: " + shortName + " has a parameter with type: ";
        msg += cls.getSimpleName();
        msg += ". Replace this parameter type with double and the procedure may compile.";
        throw compiler.new VoltCompilerException(msg);
      }

      VoltType type;
      try {
        type = VoltType.typeFromClass(cls);
      } catch (VoltTypeException e) {
        // handle the case where the type is invalid
        String msg = "Procedure: " + shortName + " has a parameter with invalid type: ";
        msg += cls.getSimpleName();
        throw compiler.new VoltCompilerException(msg);
      } catch (RuntimeException e) {
        String msg =
            "Procedure: " + shortName + " unexpectedly failed a check on a parameter of type: ";
        msg += cls.getSimpleName();
        msg += " with error: ";
        msg += e.toString();
        throw compiler.new VoltCompilerException(msg);
      }

      param.setType(type.getValue());
    }

    // parse the procinfo
    procedure.setSinglepartition(info.singlePartition);
    if (info.singlePartition) {
      parsePartitionInfo(compiler, db, procedure, info.partitionInfo);
      if (procedure.getPartitionparameter() >= paramTypes.length) {
        String msg =
            "PartitionInfo parameter not a valid parameter for procedure: "
                + procedure.getClassname();
        throw compiler.new VoltCompilerException(msg);
      }

      // check the type of partition parameter meets our high standards
      Class<?> partitionType = paramTypes[procedure.getPartitionparameter()];
      Class<?>[] validPartitionClzzes = {
        Long.class, Integer.class, Short.class, Byte.class,
        long.class, int.class, short.class, byte.class,
        String.class, byte[].class
      };
      boolean found = false;
      for (Class<?> candidate : validPartitionClzzes) {
        if (partitionType == candidate) found = true;
      }
      if (!found) {
        String msg =
            "PartitionInfo parameter must be a String or Number for procedure: "
                + procedure.getClassname();
        throw compiler.new VoltCompilerException(msg);
      }

      VoltType columnType = VoltType.get((byte) procedure.getPartitioncolumn().getType());
      VoltType paramType = VoltType.typeFromClass(partitionType);
      if (!columnType.canExactlyRepresentAnyValueOf(paramType)) {
        String msg =
            "Type mismatch between partition column and partition parameter for procedure "
                + procedure.getClassname()
                + " may cause overflow or loss of precision.\nPartition column is type "
                + columnType
                + " and partition parameter is type "
                + paramType;
        throw compiler.new VoltCompilerException(msg);
      } else if (!paramType.canExactlyRepresentAnyValueOf(columnType)) {
        String msg =
            "Type mismatch between partition column and partition parameter for procedure "
                + procedure.getClassname()
                + " does not allow the full range of partition key values.\nPartition column is type "
                + columnType
                + " and partition parameter is type "
                + paramType;
        compiler.addWarn(msg);
      }
    }

    // put the compiled code for this procedure into the jarfile
    // need to find the outermost ancestor class for the procedure in the event
    // that it's actually an inner (or inner inner...) class.
    // addClassToJar recursively adds all the children, which should include this
    // class
    Class<?> ancestor = procClass;
    while (ancestor.getEnclosingClass() != null) {
      ancestor = ancestor.getEnclosingClass();
    }
    compiler.addClassToJar(jarOutput, ancestor);
  }
Beispiel #12
0
  public boolean compile(
      final VoltCompiler compiler,
      final String jarPath,
      final String voltRoot,
      final DeploymentInfo deployment,
      final boolean ppdEnabled,
      final String snapshotPath,
      final String ppdPrefix) {
    assert (jarPath != null);
    assert (deployment == null || deployment.sitesPerHost >= 1);
    assert (deployment == null || deployment.hostCount >= 1);

    String deploymentVoltRoot = voltRoot;
    if (deployment != null) {
      if (voltRoot == null) {
        String voltRootPath = "/tmp/" + System.getProperty("user.name");
        java.io.File voltRootFile = new java.io.File(voltRootPath);
        if (!voltRootFile.exists()) {
          if (!voltRootFile.mkdir()) {
            throw new RuntimeException(
                "Unable to create voltdbroot \"" + voltRootPath + "\" for test");
          }
        }
        if (!voltRootFile.isDirectory()) {
          throw new RuntimeException(
              "voltdbroot \"" + voltRootPath + "\" for test exists but is not a directory");
        }
        if (!voltRootFile.canRead()) {
          throw new RuntimeException(
              "voltdbroot \"" + voltRootPath + "\" for test exists but is not readable");
        }
        if (!voltRootFile.canWrite()) {
          throw new RuntimeException(
              "voltdbroot \"" + voltRootPath + "\" for test exists but is not writable");
        }
        if (!voltRootFile.canExecute()) {
          throw new RuntimeException(
              "voltdbroot \"" + voltRootPath + "\" for test exists but is not writable");
        }
        deploymentVoltRoot = voltRootPath;
      }
    }
    m_voltRootPath = deploymentVoltRoot;

    // Add the DDL in the transformer to the schema files before compilation
    try {
      addLiteralSchema(transformer.toString());
      transformer = new StringBuffer();
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    }

    String[] schemaPath = m_schemas.toArray(new String[0]);

    compiler.setProcInfoOverrides(m_procInfoOverrides);
    if (m_diagnostics != null) {
      compiler.enableDetailedCapture();
    }

    boolean success = false;
    try {
      success = compiler.compileFromDDL(jarPath, schemaPath);
    } catch (VoltCompilerException e1) {
      e1.printStackTrace();
      return false;
    }

    m_diagnostics = compiler.harvestCapturedDetail();
    if (m_compilerDebugPrintStream != null) {
      if (success) {
        compiler.summarizeSuccess(m_compilerDebugPrintStream, m_compilerDebugPrintStream, jarPath);
      } else {
        compiler.summarizeErrors(m_compilerDebugPrintStream, m_compilerDebugPrintStream);
      }
    }
    if (deployment != null) {
      try {
        m_pathToDeployment = writeDeploymentFile(deploymentVoltRoot, deployment);
      } catch (Exception e) {
        System.out.println("Failed to create deployment file in testcase.");
        e.printStackTrace();
        System.out.println("hostcount: " + deployment.hostCount);
        System.out.println("sitesPerHost: " + deployment.sitesPerHost);
        System.out.println("replication: " + deployment.replication);
        System.out.println("voltRoot: " + deploymentVoltRoot);
        System.out.println("ppdEnabled: " + ppdEnabled);
        System.out.println("snapshotPath: " + snapshotPath);
        System.out.println("ppdPrefix: " + ppdPrefix);
        System.out.println("adminEnabled: " + deployment.useCustomAdmin);
        System.out.println("adminPort: " + deployment.adminPort);
        System.out.println("adminOnStartup: " + deployment.adminOnStartup);

        // sufficient to escape and fail test cases?
        throw new RuntimeException(e);
      }
    }

    return success;
  }
  public void testGetIndexInfo() throws Exception {
    String schema =
        "create table Table1 (Column1 smallint ASSUMEUNIQUE, Column2 integer, Column3 bigint not null, Column4 integer, Column5 integer, "
            + "  constraint pk_tree primary key (Column1, Column3));"
            + "partition table Table1 on column Column3;"
            + "create index Index1_tree on Table1 (Column2, Column3);"
            + "create index Index2_hash on Table1 (Column4, Column5);"
            + "create procedure sample as select * from Table1;";

    VoltCompiler c = compileForDDLTest2(schema);
    System.out.println(c.getCatalog().serialize());
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
    VoltTable indexes = dut.getMetaData("IndexInfo");
    System.out.println(indexes);
    assertEquals(13, indexes.getColumnCount());
    assertEquals(7, indexes.getRowCount());
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes, "INDEX_NAME", "INDEX1_TREE", "COLUMN_NAME", "Column2"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 1, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(java.sql.DatabaseMetaData.tableIndexOther, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 1, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals("A", indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes, "INDEX_NAME", "INDEX1_TREE", "COLUMN_NAME", "Column3"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 1, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(java.sql.DatabaseMetaData.tableIndexOther, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 2, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals("A", indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes, "INDEX_NAME", "INDEX2_HASH", "COLUMN_NAME", "Column4"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 1, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(
        java.sql.DatabaseMetaData.tableIndexHashed, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 1, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals(null, indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes, "INDEX_NAME", "INDEX2_HASH", "COLUMN_NAME", "Column5"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 1, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(
        java.sql.DatabaseMetaData.tableIndexHashed, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 2, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals(null, indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes,
            "INDEX_NAME",
            HSQLInterface.AUTO_GEN_CONSTRAINT_WRAPPER_PREFIX + "PK_TREE",
            "COLUMN_NAME",
            "Column1"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 0, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(java.sql.DatabaseMetaData.tableIndexOther, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 1, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals("A", indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes,
            "INDEX_NAME",
            HSQLInterface.AUTO_GEN_CONSTRAINT_WRAPPER_PREFIX + "PK_TREE",
            "COLUMN_NAME",
            "Column3"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 0, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(java.sql.DatabaseMetaData.tableIndexOther, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 2, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals("A", indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertTrue(
        VoltTableTestHelpers.moveToMatchingTupleRow(
            indexes,
            "INDEX_NAME",
            HSQLInterface.AUTO_GEN_CONSTRAINT_PREFIX + "TABLE1_COLUMN1",
            "COLUMN_NAME",
            "Column1"));
    assertEquals("TABLE1", indexes.get("TABLE_NAME", VoltType.STRING));
    assertEquals((byte) 0, indexes.get("NON_UNIQUE", VoltType.TINYINT));
    assertEquals(java.sql.DatabaseMetaData.tableIndexOther, indexes.get("TYPE", VoltType.SMALLINT));
    assertEquals((short) 1, indexes.get("ORDINAL_POSITION", VoltType.SMALLINT));
    assertEquals("A", indexes.get("ASC_OR_DESC", VoltType.STRING));
    assertFalse(VoltTableTestHelpers.moveToMatchingRow(indexes, "COLUMN_NAME", "NotAColumn"));
  }
  public void testGetColumns() throws Exception {
    HashMap<String, Object[]> refcolumns = new HashMap<String, Object[]>();
    refcolumns.put(
        "Column1",
        new Object[] {
          java.sql.Types.VARCHAR,
          "VARCHAR",
          200,
          null,
          null,
          java.sql.DatabaseMetaData.columnNoNulls,
          null,
          null,
          200,
          1,
          "NO"
        });
    refcolumns.put(
        "Column2",
        new Object[] {
          java.sql.Types.TINYINT,
          "TINYINT",
          7,
          null,
          2,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          null,
          2,
          "YES"
        });
    refcolumns.put(
        "Column3",
        new Object[] {
          java.sql.Types.SMALLINT,
          "SMALLINT",
          15,
          null,
          2,
          java.sql.DatabaseMetaData.columnNoNulls,
          "PARTITION_COLUMN",
          null,
          null,
          1,
          "NO"
        });
    refcolumns.put(
        "Column4",
        new Object[] {
          java.sql.Types.INTEGER,
          "INTEGER",
          31,
          null,
          2,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          null,
          2,
          "YES"
        });
    refcolumns.put(
        "Column5",
        new Object[] {
          java.sql.Types.BIGINT,
          "BIGINT",
          63,
          null,
          2,
          java.sql.DatabaseMetaData.columnNoNulls,
          null,
          null,
          null,
          3,
          "NO"
        });
    refcolumns.put(
        "Column6",
        new Object[] {
          java.sql.Types.FLOAT,
          "FLOAT",
          53,
          null,
          2,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          null,
          1,
          "YES"
        });
    refcolumns.put(
        "Column7",
        new Object[] {
          java.sql.Types.TIMESTAMP,
          "TIMESTAMP",
          63,
          null,
          2,
          java.sql.DatabaseMetaData.columnNoNulls,
          null,
          null,
          null,
          2,
          "NO"
        });
    refcolumns.put(
        "Column8",
        new Object[] {
          java.sql.Types.DECIMAL,
          "DECIMAL",
          VoltDecimalHelper.kDefaultPrecision,
          VoltDecimalHelper.kDefaultScale,
          10,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          null,
          3,
          "YES"
        });
    refcolumns.put(
        "Column9",
        new Object[] {
          java.sql.Types.VARBINARY,
          "VARBINARY",
          250,
          null,
          null,
          java.sql.DatabaseMetaData.columnNoNulls,
          null,
          null,
          250,
          1,
          "NO"
        });
    refcolumns.put(
        "Column10",
        new Object[] {
          java.sql.Types.VARCHAR,
          "VARCHAR",
          200,
          null,
          null,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          200,
          1,
          "YES"
        });
    refcolumns.put(
        "Column11",
        new Object[] {
          java.sql.Types.INTEGER,
          "INTEGER",
          31,
          null,
          2,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          null,
          null,
          2,
          "YES"
        });
    refcolumns.put(
        "Default1",
        new Object[] {
          java.sql.Types.TINYINT,
          "TINYINT",
          7,
          null,
          2,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          "10",
          null,
          1,
          "YES"
        });
    refcolumns.put(
        "Default2",
        new Object[] {
          java.sql.Types.VARCHAR,
          "VARCHAR",
          50,
          null,
          null,
          java.sql.DatabaseMetaData.columnNullable,
          null,
          "'DUDE'",
          50,
          2,
          "YES"
        });

    String schema =
        "create table Table1 (Column1 varchar(200) not null, Column2 tinyint);"
            + "create table Table2 (Column3 smallint not null, Column4 integer, Column5 bigint not null);"
            + "partition table Table2 on column Column3;"
            + "create table Table3 (Column6 float, Column7 timestamp not null, Column8 decimal);"
            + "create table Table4 (Column9 varbinary(250) not null);"
            + "create view View1 (Column10, Column11) as select Column1, count(*) from Table1 group by Column1;"
            + "create table Table5 (Default1 tinyint default 10, Default2 varchar(50) default 'DUDE');"
            + "create procedure sample as select * from Table1;";

    VoltCompiler c = compileForDDLTest2(schema);
    System.out.println(c.getCatalog().serialize());
    JdbcDatabaseMetaDataGenerator dut =
        new JdbcDatabaseMetaDataGenerator(c.getCatalog(), null, new InMemoryJarfile(testout_jar));
    VoltTable columns = dut.getMetaData("ColUmns");
    System.out.println(columns);
    assertEquals(23, columns.getColumnCount());
    assertEquals(13, columns.getRowCount());
    for (Map.Entry<String, Object[]> entry : refcolumns.entrySet()) {
      verifyColumnData(entry.getKey(), columns, entry.getValue());
    }
  }
Beispiel #15
0
  public boolean compile(
      final VoltCompiler compiler,
      final String jarPath,
      final int sitesPerHost,
      final int hostCount,
      final int replication,
      final String leaderAddress) {
    assert (jarPath != null);
    assert (sitesPerHost >= 1);
    assert (hostCount >= 1);
    assert (leaderAddress != null);

    // this stuff could all be converted to org.voltdb.compiler.projectfile.*
    // jaxb objects and (WE ARE!) marshaled to XML. Just needs some elbow grease.

    DocumentBuilderFactory docFactory;
    DocumentBuilder docBuilder;
    Document doc;
    try {
      docFactory = DocumentBuilderFactory.newInstance();
      docBuilder = docFactory.newDocumentBuilder();
      doc = docBuilder.newDocument();
    } catch (final ParserConfigurationException e) {
      e.printStackTrace();
      return false;
    }

    // <project>
    final Element project = doc.createElement("project");
    doc.appendChild(project);

    // <security>
    final Element security = doc.createElement("security");
    security.setAttribute("enabled", Boolean.valueOf(m_securityEnabled).toString());
    project.appendChild(security);

    // <database>
    final Element database = doc.createElement("database");
    database.setAttribute("name", "database");
    database.setAttribute("project", this.project_name);
    project.appendChild(database);
    buildDatabaseElement(doc, database);

    // boilerplate to write this DOM object to file.
    StreamResult result;
    try {
      final Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      result = new StreamResult(new StringWriter());
      final DOMSource domSource = new DOMSource(doc);
      transformer.transform(domSource, result);
    } catch (final TransformerConfigurationException e) {
      e.printStackTrace();
      return false;
    } catch (final TransformerFactoryConfigurationError e) {
      e.printStackTrace();
      return false;
    } catch (final TransformerException e) {
      e.printStackTrace();
      return false;
    }

    //        String xml = result.getWriter().toString();
    //        System.out.println(xml);

    final File projectFile = writeStringToTempFile(result.getWriter().toString());
    final String projectPath = projectFile.getPath();
    LOG.debug("PROJECT XML: " + projectPath);

    ClusterConfig cc =
        (this.cluster_config.isEmpty()
            ? new ClusterConfig(hostCount, sitesPerHost, replication, leaderAddress)
            : this.cluster_config);
    final boolean success =
        compiler.compile(projectPath, cc, jarPath, m_compilerDebugPrintStream, m_procInfoOverrides);

    // HACK: If we have a ParameterMappingsSet that we need to apply
    // either from a file or a fixed mappings, then we have
    // to load the catalog into this JVM, apply the mappings, and then
    // update the jar file with the new catalog
    if (m_paramMappingsFile != null || m_paramMappings.isEmpty() == false) {
      File jarFile = new File(jarPath);
      Catalog catalog = CatalogUtil.loadCatalogFromJar(jarFile);
      assert (catalog != null);
      Database catalog_db = CatalogUtil.getDatabase(catalog);

      this.applyParameterMappings(catalog_db);

      // Construct a List of prefetchable Statements
      this.applyPrefetchableFlags(catalog_db);

      // Write it out!
      try {
        CatalogUtil.updateCatalogInJar(jarFile, catalog, m_paramMappingsFile);
      } catch (Exception ex) {
        String msg = "Failed to updated Catalog in jar file '" + jarPath + "'";
        throw new RuntimeException(msg, ex);
      }
    }

    return success;
  }
Beispiel #16
0
  public static final void addClassToJar(final Class<?> cls, final VoltCompiler compiler)
      throws VoltCompiler.VoltCompilerException {

    if (cachedAddedClasses.contains(cls)) {
      return;
    } else {
      cachedAddedClasses.add(cls);
    }

    for (final Class<?> nested : cls.getDeclaredClasses()) {
      addClassToJar(nested, compiler);
    }

    String packagePath = cls.getName();
    packagePath = packagePath.replace('.', '/');
    packagePath += ".class";

    String realName = cls.getName();
    realName = realName.substring(realName.lastIndexOf('.') + 1);
    realName += ".class";

    final URL absolutePath = cls.getResource(realName);
    File file = null;

    InputStream fis = null;
    int fileSize = 0;
    try {
      file = new File(URLDecoder.decode(absolutePath.getFile(), "UTF-8"));
      fis = new FileInputStream(file);
      assert (file.canRead());
      assert (file.isFile());
      fileSize = (int) file.length();
    } catch (final FileNotFoundException e) {
      try {
        final String contents = JarReader.readFileFromJarfile(absolutePath.getPath());
        fis = new StringInputStream(contents);
        fileSize = contents.length();
      } catch (final Exception e2) {
        final String msg = "Unable to locate classfile for " + realName;
        throw compiler.new VoltCompilerException(msg);
      }
    } catch (final UnsupportedEncodingException e) {
      e.printStackTrace();
      System.exit(-1);
    }

    assert (fileSize > 0);
    int readSize = 0;

    final byte[] fileBytes = new byte[fileSize];

    try {
      while (readSize < fileSize) {
        readSize = fis.read(fileBytes, readSize, fileSize - readSize);
      }
    } catch (final IOException e) {
      final String msg = "Unable to read (or completely read) classfile for " + realName;
      throw compiler.new VoltCompilerException(msg);
    }

    compiler.addEntryToJarOutput(packagePath, fileBytes);
  }