private static void processDocument()

in calcite-adapter/src/main/java/software/amazon/documentdb/jdbc/metadata/DocumentDbTableSchemaGenerator.java [124:234]


    private static void processDocument(
            final BsonDocument document,
            final Map<String, DocumentDbSchemaTable> tableMap,
            final List<DocumentDbMetadataColumn> foreignKeys,
            final String path,
            final String collectionName,
            final boolean isRootDocument,
            final Map<String, String> tableNameMap) {

        // Need to preserve order of fields.
        final LinkedHashMap<String, DocumentDbSchemaColumn> columnMap = new LinkedHashMap<>();

        final String tableName = toName(combinePath(collectionName, path), tableNameMap);
        if (tableMap.containsKey(tableName)) {
            // If we've already visited this document/table,
            // start with the previously discovered columns.
            // This will have included and primary/foreign key definitions.
            columnMap.putAll(tableMap.get(tableName).getColumnMap());
        } else {
            // Add foreign keys.
            //
            // Foreign key(s) are the primary key(s) passed from the parent table.
            // Minimally, this is the primary key for the "_id" field.
            //
            // If called from an array parent, it will also include the "index_lvl_<n>"
            // column(s) from the previous level in the array.
            //
            // The primaryKeyColumn and foreignKeyColumn are the one-indexed value
            // referencing the order withing the primary or foreign key column.
            int primaryKeyColumn = KEY_COLUMN_NONE;
            for (DocumentDbMetadataColumn column : foreignKeys) {
                primaryKeyColumn++;
                buildForeignKeysFromDocument(columnMap, tableName, primaryKeyColumn, column);
            }
        }

        final Map<String, String> columnNameMap = columnMap.values().stream().collect(
                Collectors.toMap(
                        DocumentDbSchemaColumn::getSqlName,
                        DocumentDbSchemaColumn::getSqlName));
        // Process all fields in the document
        for (Entry<String, BsonValue> entry : document.entrySet()) {
            final String fieldName = entry.getKey();
            final String fieldPath = combinePath(path, fieldName);
            final BsonValue bsonValue = entry.getValue();
            final BsonType bsonType = bsonValue.getBsonType();
            final boolean isPrimaryKey = isRootDocument && isIdField(fieldName);
            final String columnName = getFieldNameIfIsPrimaryKey(
                    collectionName, fieldName, isPrimaryKey, columnNameMap);
            final DocumentDbMetadataColumn prevMetadataColumn = (DocumentDbMetadataColumn) columnMap
                    .getOrDefault(columnName, null);

            // ASSUMPTION: relying on the behaviour that the "_id" field will ALWAYS be first
            // in the root document.
            final JdbcType prevSqlType = getPrevSqlTypeOrDefault(prevMetadataColumn);
            final JdbcType nextSqlType = getSqlTypeIfIsPrimaryKey(bsonType, prevSqlType, isPrimaryKey);
            if (LOGGER.isDebugEnabled()) {
                final JdbcType currentDocType = getSqlTypeIfIsPrimaryKey(bsonType, JdbcType.NULL, isPrimaryKey);
                if (!prevSqlType.equals(currentDocType) && prevMetadataColumn != null) {
                    LOGGER.debug(String.format("Type conflict in table %s, types %s and %s mapped to %s.",
                            tableName, prevSqlType.name(), currentDocType, nextSqlType.name()));
                }
            }

            processComplexTypes(
                    tableMap,
                    new ArrayList<>(foreignKeys),
                    collectionName,
                    entry,
                    fieldPath,
                    bsonType,
                    prevMetadataColumn,
                    nextSqlType,
                    tableNameMap);
            final DocumentDbMetadataColumn metadataColumn = DocumentDbMetadataColumn
                    .builder()
                    .fieldPath(fieldPath)
                    .sqlName(columnName)
                    .sqlType(nextSqlType)
                    .dbType(getPromotedBsonType(bsonType, prevMetadataColumn))
                    .isIndex(false)
                    .isPrimaryKey(isPrimaryKey)
                    .index(getPrevIndexOrDefault(prevMetadataColumn, columnMap.size() + 1))
                    .tableName(tableName)
                    .primaryKeyIndex(getPrimaryKeyColumn(isPrimaryKey))
                    .foreignKeyIndex(KEY_COLUMN_NONE)
                    .isGenerated(false)
                    .virtualTableName(getVirtualTableNameIfIsPrimaryKey(
                            fieldPath, nextSqlType, isPrimaryKey, collectionName, tableNameMap))
                    .build();
            columnMap.put(metadataColumn.getSqlName(), metadataColumn);
            addToForeignKeysIfIsPrimary(foreignKeys, isPrimaryKey, metadataColumn);
        }

        // Ensure virtual table primary key column data types are consistent.
        if (isRootDocument) {
            checkVirtualTablePrimaryKeys(tableMap, collectionName, columnMap, columnNameMap);
        }

        // Add virtual table.
        final DocumentDbMetadataTable metadataTable = DocumentDbMetadataTable
                .builder()
                .sqlName(tableName)
                .collectionName(collectionName)
                .columns(columnMap)
                .build();
        if (LOGGER.isDebugEnabled() && !tableMap.containsKey(metadataTable.getSqlName())) {
            LOGGER.debug(String.format("Added schema for table %s.", metadataTable.getSqlName()));
        }
        tableMap.put(metadataTable.getSqlName(), metadataTable);
    }