private void setStrategy(String name, DataNode dataNode) {
   dataNode.setSchemaUpdateStrategyName(name);
   try {
     dataNode.setSchemaUpdateStrategy(
         (SchemaUpdateStrategy)
             Class.forName(dataNode.getSchemaUpdateStrategyName()).newInstance());
   } catch (Exception e) {
     throw new CayenneRuntimeException(e);
   }
 }
 private void dropTables(DataMap map, DataNode dataNode, MockOperationObserver observer) {
   Collection<DbEntity> ent = map.getDbEntities();
   Iterator<DbEntity> iterator = ent.iterator();
   while (iterator.hasNext()) {
     Collection<String> collectionDrop =
         dataNode.getAdapter().dropTableStatements(iterator.next());
     for (String s : collectionDrop) {
       SQLTemplate queryDrop = new SQLTemplate(Object.class, s);
       dataNode.performQueries(Collections.singletonList((Query) queryDrop), observer);
     }
   }
 }
  public void testNoStandartSchema() {
    String template = "SELECT #result('ARTIST_ID' 'int') FROM ARTIST ORDER BY ARTIST_ID";
    SQLTemplate query = new SQLTemplate(Object.class, template);
    MockOperationObserver observer = new MockOperationObserver();
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    DataNode dataNode = createDataNode(map);

    setStrategy(TestSchemaUpdateStrategy.class.getName(), dataNode);

    dataNode.performQueries(Collections.singletonList((Query) query), observer);
    assertTrue(dataNode.getSchemaUpdateStrategy() instanceof TestSchemaUpdateStrategy);
  }
 private DataNode createDataNode(DataMap map) {
   Collection<DataMap> colection = new ArrayList<DataMap>();
   colection.add(map);
   DataNode dataNode = new DataNode();
   dataNode.setJdbcEventLogger(jdbcEventLogger);
   dataNode.setDataMaps(colection);
   dataNode.setAdapter(adapter);
   dataNode.setDataSource(dataSourceFactory.getSharedDataSource());
   dataNode.setDataSourceFactory(node.getDataSourceFactory());
   dataNode.setSchemaUpdateStrategyName(node.getSchemaUpdateStrategyName());
   dataNode.setEntityResolver(new EntityResolver(colection));
   return dataNode;
 }
  private DbEntity createOneTable(DataNode dataNode) {
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    Collection<DbEntity> ent = map.getDbEntities();
    DbEntity entity = ent.iterator().next();
    String template = dataNode.getAdapter().createTable(entity);

    SQLTemplate query = new SQLTemplate(Object.class, template);
    MockOperationObserver observer = new MockOperationObserver();

    setStrategy(null, dataNode);

    dataNode.performQueries(Collections.singletonList((Query) query), observer);
    return entity;
  }
  public void testMixedStrategyTableNoExist() throws Exception {

    String template = "SELECT #result('id' 'int') FROM SUS1";
    SQLTemplate query = new SQLTemplate(Object.class, template);
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    DataNode dataNode = createDataNode(map);
    int sizeDB = getNameTablesInDB(dataNode).size();
    MockOperationObserver observer = new MockOperationObserver();

    setStrategy(ThrowOnPartialOrCreateSchemaStrategy.class.getName(), dataNode);

    try {
      dataNode.performQueries(Collections.singletonList((Query) query), observer);
      Map<String, Boolean> nameTables = getNameTablesInDB(dataNode);
      assertTrue(nameTables.get("sus1") != null || nameTables.get("SUS1") != null);
      int sizeDB2 = getNameTablesInDB(dataNode).size();
      assertEquals(2, sizeDB2 - sizeDB);
      dataNode.performQueries(Collections.singletonList((Query) query), observer);
      int sizeDB3 = getNameTablesInDB(dataNode).size();
      assertEquals(sizeDB2, sizeDB3);
    } finally {
      DataNode dataNode2 = createDataNode(map);
      dataNode2.setSchemaUpdateStrategy(
          (SchemaUpdateStrategy)
              Class.forName(dataNode2.getSchemaUpdateStrategyName()).newInstance());
      dropTables(map, dataNode2, observer);
    }
    assertEquals(getNameTablesInDB(dataNode).size(), sizeDB);
  }
예제 #7
0
  @Override
  public Map<String, DataSource> dataSources() {

    Map<String, DataSource> dataSources = new HashMap<>();

    for (DataNode n : runtime.getDataDomain().getDataNodes()) {

      // this method is used to seed a special kind of JdbcConnector.
      // But note that the DataSource here is attached to the DataNode
      // transaction, so reading source data will happen over the same
      // connection as writing target data. Hopefully such multiplexing
      // the connection works ok...

      dataSources.put(n.getName(), n.getDataSource());
    }

    return dataSources;
  }
  private void generateDBWithDBGeneratorStrategy(
      DataNode dataNode, SQLTemplate query, MockOperationObserver observer) {

    setStrategy(CreateIfNoSchemaStrategy.class.getName(), dataNode);

    dataNode.performQueries(Collections.singletonList((Query) query), observer);
    Map<String, Boolean> nameTables = getNameTablesInDB(dataNode);
    assertTrue(nameTables.get("sus1") != null || nameTables.get("SUS1") != null);
  }
  private void tableExistfForThrowOnPartialAndMixStrategy(String strategy) throws Exception {

    String template = "SELECT #result('ARTIST_ID' 'int') FROM ARTIST ORDER BY ARTIST_ID";
    SQLTemplate query = new SQLTemplate(Object.class, template);
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    MockOperationObserver observer = new MockOperationObserver();
    DataNode dataNode = createDataNode(map);
    int sizeDB = getNameTablesInDB(dataNode).size();
    generateDBWithDBGeneratorStrategy(dataNode, query, observer);
    int sizeDB2 = getNameTablesInDB(dataNode).size();
    assertEquals(2, sizeDB2 - sizeDB);
    try {
      DataNode dataNode2 = createDataNode(map);
      setStrategy(strategy, dataNode2);
      dataNode2.performQueries(Collections.singletonList((Query) query), observer);
    } finally {
      dropTables(map, dataNode, observer);
    }
  }
  /** @since 3.0 */
  @Override
  protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
    // handle CAY-588 - get connection that is separate from the connection in the
    // current transaction.

    // TODO (andrus, 7/6/2006) Note that this will still work in a pool with a single
    // connection, as PK generator is invoked early in the transaction, before the
    // connection is grabbed for commit... So maybe promote this to other adapters in
    // 3.0?

    Transaction transaction = Transaction.getThreadTransaction();
    Transaction.bindThreadTransaction(null);

    try {

      Connection connection = node.getDataSource().getConnection();
      try {
        CallableStatement statement = connection.prepareCall("{call auto_pk_for_table(?, ?)}");
        try {
          statement.setString(1, entity.getName());
          statement.setInt(2, super.getPkCacheSize());

          // can't use "executeQuery"
          // per http://jtds.sourceforge.net/faq.html#expectingResultSet
          statement.execute();
          if (statement.getMoreResults()) {
            ResultSet rs = statement.getResultSet();

            try {
              if (rs.next()) {
                return rs.getLong(1);
              } else {
                throw new CayenneRuntimeException(
                    "Error generating pk for DbEntity " + entity.getName());
              }
            } finally {
              rs.close();
            }
          } else {
            throw new CayenneRuntimeException(
                "Error generating pk for DbEntity "
                    + entity.getName()
                    + ", no result set from stored procedure.");
          }
        } finally {
          statement.close();
        }
      } finally {
        connection.close();
      }
    } finally {
      Transaction.bindThreadTransaction(transaction);
    }
  }
  public void testDBGeneratorStrategy() throws Exception {

    String template = "SELECT #result('id' 'int') FROM SUS1";
    SQLTemplate query = new SQLTemplate(Object.class, template);

    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    DataNode dataNode = createDataNode(map);
    int sizeDB = getNameTablesInDB(dataNode).size();
    MockOperationObserver observer = new MockOperationObserver();
    try {

      generateDBWithDBGeneratorStrategy(dataNode, query, observer);
      int sizeDB2 = getNameTablesInDB(dataNode).size();
      assertEquals(2, sizeDB2 - sizeDB);
      dataNode.performQueries(Collections.singletonList((Query) query), observer);
      int sizeDB3 = getNameTablesInDB(dataNode).size();
      assertEquals(sizeDB2, sizeDB3);
    } finally {
      DataNode dataNode2 = createDataNode(map);
      dataNode2.setSchemaUpdateStrategy(
          (SchemaUpdateStrategy)
              Class.forName(dataNode2.getSchemaUpdateStrategyName()).newInstance());
      dropTables(map, dataNode2, observer);
    }
    assertEquals(getNameTablesInDB(dataNode).size(), sizeDB);
  }
  public void testThrowOnPartialStrategyTableNoExist() throws Exception {

    String template = "SELECT #result('ARTIST_ID' 'int') FROM ARTIST ORDER BY ARTIST_ID";
    SQLTemplate query = new SQLTemplate(Object.class, template);
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    MockOperationObserver observer = new MockOperationObserver();
    DataNode dataNode = createDataNode(map);

    setStrategy(ThrowOnPartialSchemaStrategy.class.getName(), dataNode);

    try {
      dataNode.performQueries(Collections.singletonList((Query) query), observer);
    } catch (CayenneRuntimeException e) {
      assertNotNull(e);
    }

    try {
      dataNode.performQueries(Collections.singletonList((Query) query), observer);
    } catch (CayenneRuntimeException e) {
      assertNotNull(e);
    }
  }
 private Map<String, Boolean> getNameTablesInDB(DataNode dataNode) {
   String tableLabel = dataNode.getAdapter().tableTypeForTable();
   Connection con = null;
   Map<String, Boolean> nameTables = new HashMap<String, Boolean>();
   try {
     con = dataNode.getDataSource().getConnection();
     ResultSet rs = con.getMetaData().getTables(null, null, "%", new String[] {tableLabel});
     while (rs.next()) {
       String name = rs.getString("TABLE_NAME");
       nameTables.put(name, false);
     }
     rs.close();
   } catch (SQLException e) {
     throw new CayenneRuntimeException(e);
   } finally {
     try {
       con.close();
     } catch (SQLException e) {
       throw new CayenneRuntimeException(e);
     }
   }
   return nameTables;
 }
  /**
   * Runs JDBC update over a Connection obtained from DataNode. Returns a number of objects returned
   * from update.
   *
   * @throws SQLException in case of query failure.
   */
  public int runUpdate(DataNode node, String sql) throws SQLException {
    adapter.getJdbcEventLogger().logQuery(sql, Collections.EMPTY_LIST);

    Connection con = node.getDataSource().getConnection();
    try {
      Statement upd = con.createStatement();
      try {
        return upd.executeUpdate(sql);
      } finally {
        upd.close();
      }
    } finally {
      con.close();
    }
  }
  /**
   * Performs primary key generation ignoring cache. Generates a range of primary keys as specified
   * by "pkCacheSize" bean property.
   *
   * <p>This method is called internally from "generatePkForDbEntity" and then generated range of
   * key values is saved in cache for performance. Subclasses that implement different primary key
   * generation solutions should override this method, not "generatePkForDbEntity".
   *
   * @since 3.0
   */
  protected long longPkFromDatabase(DataNode node, DbEntity entity) throws Exception {
    String select =
        "SELECT #result('NEXT_ID' 'long' 'NEXT_ID') "
            + "FROM AUTO_PK_SUPPORT "
            + "WHERE TABLE_NAME = '"
            + entity.getName()
            + '\'';

    // run queries via DataNode to utilize its transactional behavior
    List<Query> queries = new ArrayList<Query>(2);
    queries.add(new SQLTemplate(entity, select));
    queries.add(new SQLTemplate(entity, pkUpdateString(entity.getName())));

    PkRetrieveProcessor observer = new PkRetrieveProcessor(entity.getName());
    node.performQueries(queries, observer);
    return observer.getId();
  }
  /** Checks if AUTO_PK_TABLE already exists in the database. */
  protected boolean autoPkTableExists(DataNode node) throws SQLException {
    Connection con = node.getDataSource().getConnection();
    boolean exists = false;
    try {
      DatabaseMetaData md = con.getMetaData();
      ResultSet tables = md.getTables(null, null, "AUTO_PK_SUPPORT", null);
      try {
        exists = tables.next();
      } finally {
        tables.close();
      }
    } finally {
      // return connection to the pool
      con.close();
    }

    return exists;
  }
  private void withOneTableForThrowOnPartialAndMixStrategy(String strategy) {
    DbEntity entity = null;
    String template = "SELECT #result('ARTIST_ID' 'int') FROM ARTIST ORDER BY ARTIST_ID";
    SQLTemplate query = new SQLTemplate(Object.class, template);
    DataMap map = node.getEntityResolver().getDataMap("sus-map");
    MockOperationObserver observer = new MockOperationObserver();
    DataNode dataNode = createDataNode(map);

    DataNode dataNode2 = createDataNode(map);

    try {

      int sizeDB = getNameTablesInDB(dataNode).size();
      entity = createOneTable(dataNode);
      int sizeDB2 = getNameTablesInDB(dataNode).size();
      assertEquals(1, sizeDB2 - sizeDB);
      setStrategy(strategy, dataNode2);
      dataNode2.performQueries(Collections.singletonList((Query) query), observer);

    } catch (CayenneRuntimeException e) {
      assertNotNull(e);
    }
    try {
      dataNode2.performQueries(Collections.singletonList((Query) query), observer);
    } catch (CayenneRuntimeException e) {
      assertNotNull(e);
    } finally {

      if (entity != null) {

        Collection<String> template2 = dataNode.getAdapter().dropTableStatements(entity);
        Iterator<String> it = template2.iterator();
        List<Query> list = new ArrayList<Query>();
        while (it.hasNext()) {
          SQLTemplate q = new SQLTemplate(Object.class, it.next());
          list.add(q);
        }
        dataNode.performQueries(list, observer);
      }
    }
  }
예제 #18
0
  @Override
  public DataNode createDataNode(DataNodeDescriptor nodeDescriptor) throws Exception {

    DataNode dataNode = new DataNode(nodeDescriptor.getName());

    dataNode.setJdbcEventLogger(jdbcEventLogger);
    dataNode.setRowReaderFactory(rowReaderFactory);
    dataNode.setBatchTranslatorFactory(batchTranslatorFactory);

    dataNode.setDataSourceLocation(nodeDescriptor.getParameters());

    DataSource dataSource = dataSourceFactory.getDataSource(nodeDescriptor);

    dataNode.setDataSourceFactory(nodeDescriptor.getDataSourceFactoryType());
    dataNode.setDataSource(dataSource);

    // schema update strategy
    String schemaUpdateStrategyType = nodeDescriptor.getSchemaUpdateStrategyType();

    if (schemaUpdateStrategyType == null) {
      dataNode.setSchemaUpdateStrategy(defaultSchemaUpdateStrategy);
      dataNode.setSchemaUpdateStrategyName(defaultSchemaUpdateStrategy.getClass().getName());
    } else {
      SchemaUpdateStrategy strategy =
          objectFactory.newInstance(SchemaUpdateStrategy.class, schemaUpdateStrategyType);
      dataNode.setSchemaUpdateStrategyName(schemaUpdateStrategyType);
      dataNode.setSchemaUpdateStrategy(strategy);
    }

    // DbAdapter
    dataNode.setAdapter(adapterFactory.createAdapter(nodeDescriptor, dataSource));

    return dataNode;
  }
 /**
  * Uses PostgresActionBuilder to create the right action.
  *
  * @since 1.2
  */
 @Override
 public SQLAction getAction(Query query, DataNode node) {
   return query.createSQLAction(new PostgresActionBuilder(this, node.getEntityResolver()));
 }