code: @Override
      public MappingWithProvenance inferMissingDatatypes(MappingWithProvenance mapping, DBMetadata dbMetadata) throws UnknownDatatypeException {
          MappingDataTypeCompletion typeCompletion = new MappingDataTypeCompletion(dbMetadata,
                  settings.isDefaultDatatypeInferred(), relation2Predicate, termFactory, typeFactory, termTypeInferenceTools, immutabilityTools);
          ImmutableMap<CQIE, PPMappingAssertionProvenance> ruleMap = mapping2DatalogConverter.convert(mapping);
  
          //CQIEs are mutable
          for(CQIE rule : ruleMap.keySet()){
              typeCompletion.insertDataTyping(rule);
          }
          return datalog2MappingConverter.convertMappingRules(ruleMap, mapping.getMetadata());
      }
docs: *
  Infers missing data types.
  For each rule, gets the type from the rule head, and if absent, retrieves the type from the metadata.
  
  The behavior of type retrieval is the following for each rule:
  . build a "termOccurrenceIndex", which is a map from variables to body atoms + position.
  For ex, consider the rule: C(x, y) <- A(x, y) \wedge B(y)
  The "termOccurrenceIndex" map is {
  x \mapsTo [<A(x, y), 1>],
  y \mapsTo [<A(x, y), 2>, <B(y), 1>]
  }
  . then take the first occurrence each variable (e.g. take <A(x, y), 2> for variable y),
  and assign to the variable the corresponding column type in the DB
  (e.g. for y, the type of column 1 of table A).
  . then inductively infer the types of functions (e.g. concat, ...) from the variable types.
  Only the outermost expression is assigned a type.
  
  Assumptions:
  .rule body atoms are extensional
  .the corresponding column types are compatible (e.g the types for column 1 of A and column 1 of B)