docs: public static TableSchema deriveSchema(Map<String, String> properties) {
  		final DescriptorProperties descriptorProperties = new DescriptorProperties();
  		descriptorProperties.putProperties(properties);
  
  		final TableSchema.Builder builder = TableSchema.builder();
  
  		final TableSchema baseSchema = descriptorProperties.getTableSchema(SCHEMA);
  		for (int i = 0; i < baseSchema.getFieldCount(); i++) {
  			final String fieldName = baseSchema.getFieldNames()[i];
  			final TypeInformation<?> fieldType = baseSchema.getFieldTypes()[i];
  
  			final boolean isProctime = descriptorProperties
  				.getOptionalBoolean(SCHEMA + '.' + i + '.' + SCHEMA_PROCTIME)
  				.orElse(false);
  			final String timestampKey = SCHEMA + '.' + i + '.' + ROWTIME_TIMESTAMPS_TYPE;
  			final boolean isRowtime = descriptorProperties.containsKey(timestampKey);
  			if (!isProctime && !isRowtime) {
  				// check for aliasing
  				final String aliasName = descriptorProperties
  					.getOptionalString(SCHEMA + '.' + i + '.' + SCHEMA_FROM)
  					.orElse(fieldName);
  				builder.field(aliasName, fieldType);
  			}
  			// only use the rowtime attribute if it references a field
  			else if (isRowtime &&
  					descriptorProperties.isValue(timestampKey, ROWTIME_TIMESTAMPS_TYPE_VALUE_FROM_FIELD)) {
  				final String aliasName = descriptorProperties
  					.getString(SCHEMA + '.' + i + '.' + ROWTIME_TIMESTAMPS_FROM);
  				builder.field(aliasName, fieldType);
  			}
  		}
  
  		return builder.build();
  	}