/** INTERNAL: Return the create table statement. */
 public Writer buildCreationWriter(AbstractSession session, Writer writer)
     throws ValidationException {
   try {
     DatabasePlatform platform = session.getPlatform();
     writer.write("CREATE PACKAGE " + getFullName());
     writer.write(" AS");
     writer.write("\n");
     for (Enumeration statementsEnum = getStatements().elements();
         statementsEnum.hasMoreElements(); ) {
       writer.write((String) statementsEnum.nextElement());
       writer.write(platform.getBatchDelimiterString());
       writer.write("\n");
     }
     for (Enumeration proceduresEnum = getProcedures().elements();
         proceduresEnum.hasMoreElements(); ) {
       writer.write("\n");
       String procedureString =
           ((StoredProcedureDefinition) proceduresEnum.nextElement())
               .buildCreationWriter(session, writer)
               .toString();
       writer.write(procedureString.substring(7, procedureString.length()));
       writer.write("\n");
     }
     writer.write(platform.getBatchEndString());
     writer.write("\n" + session.getPlatform().getStoredProcedureTerminationToken());
   } catch (IOException ioException) {
     throw ValidationException.fileError(ioException);
   }
   return writer;
 }
  /** Append the string containing the SQL insert string for the given table. */
  protected SQLCall buildCallWithoutReturning(AbstractSession session) {
    SQLCall call = new SQLCall();
    call.returnNothing();

    Writer writer = new CharArrayWriter(200);
    try {
      writer.write("INSERT ");
      if (getHintString() != null) {
        writer.write(getHintString());
        writer.write(" ");
      }
      writer.write("INTO ");
      writer.write(getTable().getQualifiedNameDelimited(session.getPlatform()));
      writer.write(" (");

      Vector fieldsForTable = new Vector();
      for (Enumeration fieldsEnum = getModifyRow().keys(); fieldsEnum.hasMoreElements(); ) {
        DatabaseField field = (DatabaseField) fieldsEnum.nextElement();
        if (field.getTable().equals(getTable()) || (!field.hasTableName())) {
          fieldsForTable.addElement(field);
        }
      }

      if (fieldsForTable.isEmpty()) {
        throw QueryException.objectToInsertIsEmpty(getTable());
      }

      for (int i = 0; i < fieldsForTable.size(); i++) {
        writer.write(
            ((DatabaseField) fieldsForTable.elementAt(i)).getNameDelimited(session.getPlatform()));
        if ((i + 1) < fieldsForTable.size()) {
          writer.write(", ");
        }
      }
      writer.write(") VALUES (");

      for (int i = 0; i < fieldsForTable.size(); i++) {
        DatabaseField field = (DatabaseField) fieldsForTable.elementAt(i);
        call.appendModify(writer, field);
        if ((i + 1) < fieldsForTable.size()) {
          writer.write(", ");
        }
      }
      writer.write(")");

      call.setSQLString(writer.toString());
    } catch (IOException exception) {
      throw ValidationException.fileError(exception);
    }
    return call;
  }
 /**
  * Return if pessimistic locking/select for update nowait is supported for this test platform.
  * Currently testing supports nowait on Oracle, SQLServer. PostgreSQL also supports NOWAIT, but
  * doesn't support the outer joins used in the tests.
  */
 public static boolean isSelectForUpateNoWaitSupported(String puName) {
   AbstractSession dbSession = getDatabaseSession(puName);
   if (dbSession.isBroker()) {
     for (AbstractSession memberSession :
         ((SessionBroker) dbSession).getSessionsByName().values()) {
       if (!isSelectForUpateSupported(memberSession.getPlatform())) {
         return false;
       }
     }
     return true;
   } else {
     return isSelectForUpateNoWaitSupported(dbSession.getPlatform());
   }
 }
 protected Hashtable removeDuplicateAndValidateInfos(AbstractSession session) {
   Hashtable infoHashtable = new Hashtable();
   for (int i = 0; i < infos.size(); i++) {
     Info info1 = infos.get(i);
     info1 = (Info) info1.clone();
     DatabaseField descField = getDescriptor().buildField(info1.getField());
     if (info1.getField().getType() == null) {
       info1.setField(descField);
     } else {
       // keep the original type if specified
       info1.getField().setName(descField.getName());
       info1
           .getField()
           .setTableName(
               getDescriptor().getDefaultTable().getQualifiedNameDelimited(session.getPlatform()));
     }
     Info info2 = (Info) infoHashtable.get(info1.getField());
     if (info2 == null) {
       infoHashtable.put(info1.getField(), info1);
     } else {
       Info infoMerged = mergeInfos(info1, info2, session, getDescriptor());
       if (infoMerged != null) {
         // substitute info2 with infoMerged
         infoHashtable.put(infoMerged.getField(), infoMerged);
       } else {
         // couldn't merge info1 and info2 due to a conflict.
         // substitute info2 with info1
         infoHashtable.put(info1.getField(), info1);
       }
     }
   }
   return infoHashtable;
 }
  /**
   * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain
   * the object. Check for batch + aggregation reading.
   */
  public Object valueFromRow(
      AbstractRecord row,
      JoinedAttributeManager joinManager,
      ObjectBuildingQuery query,
      AbstractSession executionSession)
      throws DatabaseException {
    Ref ref = (Ref) row.get(getField());

    if (ref == null) {
      return null;
    }

    Struct struct;
    try {
      ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession);
      java.sql.Connection connection =
          ((DatabaseAccessor) executionSession.getAccessor()).getConnection();
      struct =
          (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, executionSession, false);
    }
    AbstractRecord targetRow =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .buildRowFromStructure(struct);
    ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount();

    return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager);
  }
  /** INTERNAL: Build a ADT structure from the row data. */
  public Struct buildStructureFromRow(
      AbstractRecord row, AbstractSession session, java.sql.Connection connection)
      throws DatabaseException {
    Struct structure;
    boolean reconnected = false;

    try {
      if (connection == null) {
        ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session);
        reconnected = true;
        connection = ((DatabaseAccessor) session.getAccessor()).getConnection();
      }

      Object[] fields = new Object[getOrderedFields().size()];
      for (int index = 0; index < getOrderedFields().size(); index++) {
        DatabaseField field = (DatabaseField) getOrderedFields().elementAt(index);
        fields[index] = row.get(field);
      }

      structure =
          session.getPlatform().createStruct(getStructureName(), fields, session, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, session, false);
    } finally {
      if (reconnected) {
        ((DatabaseAccessor) session.getAccessor()).decrementCallCount();
      }
    }

    return structure;
  }
  /**
   * INTERNAL: Build and return the appropriate field value for the specified set of nested rows.
   * The database better be expecting an ARRAY. It looks like we can ignore inheritance here....
   */
  public Object buildFieldValueFromNestedRows(
      Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException {
    Object[] fields = new Object[nestedRows.size()];
    java.sql.Connection connection = ((DatabaseAccessor) session.getAccessor()).getConnection();
    boolean reconnected = false;

    try {
      if (connection == null) {
        ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session);
        reconnected = true;
        connection = ((DatabaseAccessor) session.getAccessor()).getConnection();
      }

      int i = 0;
      for (Enumeration stream = nestedRows.elements(); stream.hasMoreElements(); ) {
        AbstractRecord nestedRow = (AbstractRecord) stream.nextElement();
        fields[i++] = this.buildStructureFromRow(nestedRow, session, connection);
      }

      return session.getPlatform().createArray(structureName, fields, session, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, session, false);
    } finally {
      if (reconnected) {
        ((DatabaseAccessor) session.getAccessor()).decrementCallCount();
      }
    }
  }
 /**
  * INTERNAL: Build the appropriate field value for the specified set of direct values. The
  * database better be expecting an ARRAY.
  */
 public Object buildFieldValueFromDirectValues(
     Vector directValues, String elementDataTypeName, AbstractSession session)
     throws DatabaseException {
   Object[] fields = Helper.arrayFromVector(directValues);
   try {
     ((DatabaseAccessor) session.getAccessor()).incrementCallCount(session);
     java.sql.Connection connection = ((DatabaseAccessor) session.getAccessor()).getConnection();
     return session.getPlatform().createArray(elementDataTypeName, fields, session, connection);
   } catch (java.sql.SQLException ex) {
     throw DatabaseException.sqlException(ex, session, false);
   } finally {
     ((DatabaseAccessor) session.getAccessor()).decrementCallCount();
   }
 }
 /** INTERNAL: */
 public void validationAfterDescriptorInitialization(AbstractSession session) {
   Hashtable mapped = new Hashtable();
   for (int operation = INSERT; operation <= UPDATE; operation++) {
     if ((main[operation][MAPPED] != null) && !main[operation][MAPPED].isEmpty()) {
       Iterator it = main[operation][MAPPED].iterator();
       while (it.hasNext()) {
         DatabaseField field = (DatabaseField) it.next();
         mapped.put(field, field);
       }
     }
   }
   if (!mapped.isEmpty()) {
     for (Enumeration fields = getDescriptor().getFields().elements();
         fields.hasMoreElements(); ) {
       DatabaseField fieldInDescriptor = (DatabaseField) fields.nextElement();
       DatabaseField fieldInMain = (DatabaseField) mapped.get(fieldInDescriptor);
       if (fieldInMain != null) {
         if (fieldInMain.getType() == null) {
           if (getDescriptor().isReturnTypeRequiredForReturningPolicy()) {
             session
                 .getIntegrityChecker()
                 .handleError(
                     DescriptorException.returningPolicyMappedFieldTypeNotSet(
                         fieldInMain.getName(), getDescriptor()));
           }
         } else if (isThereATypeConflict(fieldInMain, fieldInDescriptor)) {
           session
               .getIntegrityChecker()
               .handleError(
                   DescriptorException.returningPolicyAndDescriptorFieldTypeConflict(
                       fieldInMain.getName(),
                       fieldInMain.getType().getName(),
                       fieldInDescriptor.getType().getName(),
                       getDescriptor()));
         }
       }
     }
   }
   if (!(session.getDatasourcePlatform() instanceof DatabasePlatform)) {
     // don't attempt further diagnostics on non-relational platforms
     return;
   }
   WriteObjectQuery[] query = {
     getDescriptor().getQueryManager().getInsertQuery(),
     getDescriptor().getQueryManager().getUpdateQuery()
   };
   String[] queryTypeName = {"InsertObjectQuery", "UpdateObjectQuery"};
   for (int operation = INSERT; operation <= UPDATE; operation++) {
     if ((main[operation][ALL] != null) && !main[operation][ALL].isEmpty()) {
       // this operation requires some fields to be returned
       if ((query[operation] == null) || (query[operation].getDatasourceCall() == null)) {
         if (!session.getPlatform().canBuildCallWithReturning()) {
           session
               .getIntegrityChecker()
               .handleError(
                   DescriptorException.noCustomQueryForReturningPolicy(
                       queryTypeName[operation],
                       Helper.getShortClassName(session.getPlatform()),
                       getDescriptor()));
         }
       } else if (query[operation].getDatasourceCall() instanceof StoredProcedureCall) {
         // SQLCall with custom SQL calculates its outputRowFields later (in prepare() method) -
         // that's why SQLCall can't be verified here.
         DatabaseCall customCall = (DatabaseCall) query[operation].getDatasourceCall();
         Enumeration outputRowFields = customCall.getOutputRowFields().elements();
         Collection notFoundInOutputRow = createCollection();
         notFoundInOutputRow.addAll(main[operation][ALL]);
         while (outputRowFields.hasMoreElements()) {
           notFoundInOutputRow.remove(outputRowFields.nextElement());
         }
         if (!notFoundInOutputRow.isEmpty()) {
           Iterator it = notFoundInOutputRow.iterator();
           while (it.hasNext()) {
             DatabaseField field = (DatabaseField) it.next();
             session
                 .getIntegrityChecker()
                 .handleError(
                     DescriptorException.customQueryAndReturningPolicyFieldConflict(
                         field.getName(), queryTypeName[operation], getDescriptor()));
           }
         }
       }
     }
   }
 }
  /** Append the string containing the SQL insert string for the given table. */
  public DatabaseCall buildCall(AbstractSession session) {
    SQLCall call = new SQLCall();
    call.returnNothing();

    Writer writer = new CharArrayWriter(100);

    Vector mainPrimaryKeys = new Vector();
    mainPrimaryKeys.addAll((Collection) tablesToPrimaryKeyFields.get(table));

    Vector allFields = (Vector) mainPrimaryKeys.clone();
    Iterator itDatabaseFieldsToValues = tables_databaseFieldsToValues.values().iterator();
    while (itDatabaseFieldsToValues.hasNext()) {
      Iterator itDatabaseFields = ((HashMap) itDatabaseFieldsToValues.next()).keySet().iterator();
      while (itDatabaseFields.hasNext()) {
        allFields.addElement(itDatabaseFields.next());
      }
    }

    try {
      // DECLARE
      writer.write("DECLARE\n");

      for (int i = 0; i < allFields.size(); i++) {
        writeDeclareTypeAndVar(
            writer, (DatabaseField) allFields.elementAt(i), session.getPlatform());
      }

      // BEGIN
      writer.write("BEGIN\n");

      //  select t0.emp_id, concat('Even', t0.f_name), t1.salary + 1000 BULK COLLECT into
      // EMPLOYEEE_EMP_ID_VAR, EMPLOYEEE_F_NAME_VAR, SALARY_SALARY_VAR from employee t0, salary t1
      // where t0.l_name like 'updateEmployeeTestUsingTempTable' and t0.f_name in ('0', '2') and
      // t1.salary = 0 and t0.emp_id = t1.emp_id;
      String selectStr = selectCall.getSQLString();
      int index = selectStr.toUpperCase().indexOf(" FROM ");
      String firstPart = selectStr.substring(0, index);
      String secondPart = selectStr.substring(index, selectStr.length());

      writer.write(tab);
      writer.write(firstPart);
      writer.write(" BULK COLLECT INTO ");

      for (int i = 0; i < allFields.size(); i++) {
        writeVar(writer, (DatabaseField) allFields.elementAt(i), session.getPlatform());
        if (i < allFields.size() - 1) {
          writer.write(", ");
        }
      }
      writer.write(secondPart);
      writer.write(";\n");

      call.getParameters().addAll(selectCall.getParameters());
      call.getParameterTypes().addAll(selectCall.getParameterTypes());

      DatabaseField firstMainPrimaryKey = (DatabaseField) mainPrimaryKeys.firstElement();
      writer.write(tab);
      writer.write("IF ");
      writeVar(writer, firstMainPrimaryKey, session.getPlatform());
      writer.write(".COUNT > 0 THEN\n");

      Iterator itEntries = tables_databaseFieldsToValues.entrySet().iterator();
      while (itEntries.hasNext()) {
        writeForAll(writer, firstMainPrimaryKey, session.getPlatform());
        writer.write(trpltab);
        writer.write("UPDATE ");
        Map.Entry entry = (Map.Entry) itEntries.next();
        DatabaseTable t = (DatabaseTable) entry.getKey();
        writer.write(t.getQualifiedNameDelimited(session.getPlatform()));
        writer.write(" SET ");
        HashMap databaseFieldsToValues = (HashMap) entry.getValue();
        int counter = 0;
        Iterator itDatabaseFields = databaseFieldsToValues.keySet().iterator();
        while (itDatabaseFields.hasNext()) {
          counter++;
          DatabaseField field = (DatabaseField) itDatabaseFields.next();
          writer.write(field.getNameDelimited(session.getPlatform()));
          writer.write(" = ");
          writeVar(writer, field, session.getPlatform());
          writer.write("(i)");
          if (counter < databaseFieldsToValues.size()) {
            writer.write(", ");
          }
        }

        writer.write(" WHERE ");

        Vector tablePrimaryKeys = new Vector();
        tablePrimaryKeys.addAll((Collection) tablesToPrimaryKeyFields.get(t));
        for (int i = 0; i < mainPrimaryKeys.size(); i++) {
          DatabaseField tableField = (DatabaseField) tablePrimaryKeys.elementAt(i);
          writer.write(tableField.getNameDelimited(session.getPlatform()));
          writer.write(" = ");
          DatabaseField mainField = (DatabaseField) mainPrimaryKeys.elementAt(i);
          writeVar(writer, mainField, session.getPlatform());
          writer.write("(i)");
          if (i < mainPrimaryKeys.size() - 1) {
            writer.write(" AND ");
          } else {
            writer.write(";\n");
          }
        }
      }

      writer.write(tab);
      writer.write("END IF;\n");

      writer.write(tab);
      DatabaseField outField = new DatabaseField("ROW_COUNT");
      outField.setType(Integer.class);
      call.appendOut(writer, outField);
      writer.write(" := ");
      writeVar(writer, firstMainPrimaryKey, session.getPlatform());
      writer.write(".COUNT;\n");

      writer.write("END;");

      call.setSQLString(writer.toString());

    } catch (IOException exception) {
      throw ValidationException.fileError(exception);
    }

    return call;
  }