All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ldbc.schemaspy.builder.TableBuilder.scala Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2023-2024 by Takahiko Tominaga
 * This software is licensed under the MIT License (MIT).
 * For more information see LICENSE or https://opensource.org/licenses/MIT
 */

package ldbc.schemaspy.builder

import org.schemaspy.model.Database as SchemaspyDatabase
import org.schemaspy.model.Table as SchemaspyTable
import org.schemaspy.model.TableIndex

import ldbc.core.*
import ldbc.core.attribute.AutoInc
import ldbc.core.validator.TableValidator

/**
 * A model for building a SchemaSpy Table model from a Table.
 *
 * If there is a problem with the Table configuration, an exception is raised by TableValidator during instance
 * creation.
 *
 * @param db
 *   A model that stores information on databases handled by SchemaSpy.
 * @param table
 *   Trait for generating SQL table information.
 */
case class TableBuilder(db: SchemaspyDatabase, table: Table[?]) extends TableValidator:

  private val comment = table.options.flatMap {
    case comment: TableOption.Comment => Some(comment.value)
    case _                            => None
  }.headOption

  private val schemaTable = new SchemaspyTable(db, null, db.getSchema.getName, table._name, comment.orNull)

  /**
   * A method to extract columns with PrimaryKey set from all columns and keys set in the Table.
   *
   * @param table
   *   Trait for generating SQL table information.
   */
  private def detectPrimaryKeyColumn(table: Table[?]): Seq[Column[?]] =
    (table.all.flatMap {
      case c: Column[?] if c.attributes.exists(_.isInstanceOf[PrimaryKey]) => Some(c)
      case _                                                               => None
    } ++ table.keyDefinitions.flatMap {
      case key: (PrimaryKey & Index) => key.keyPart
      case _                         => List.empty
    }).distinct

  /**
   * Method for extracting Index key information from Column.
   *
   * @param column
   *   Trait for representing SQL Column
   */
  private def buildIndexFromColumn(column: Column[?]): Seq[(String, Boolean)] =
    column.attributes.flatMap {
      case _: PrimaryKey  => Some(("PRIMARY", true))
      case key: UniqueKey => Some((key.indexName.getOrElse(column.label), true))
      case key: IndexKey  => Some((key.indexName.getOrElse(column.label), false))
      case v: Constraint =>
        v.key match
          case _: PrimaryKey  => Some(("PRIMARY", true))
          case key: UniqueKey => Some((key.indexName.getOrElse(column.label), true))
          case _              => None
      case _ => None
    }

  /**
   * Method for extracting Index key information from Table Key definitions.
   *
   * @param column
   *   Trait for representing SQL Column
   * @param keyDefinitions
   *   Table Key definitions
   */
  private def buildIndexFromKeyDefinitions(column: Column[?], keyDefinitions: Seq[Key]): Seq[(String, Boolean)] =
    keyDefinitions.flatMap {
      case key: (PrimaryKey & Index) if key.keyPart.contains(column) => Some(("PRIMARY", true))
      case key: (UniqueKey & Index) if key.keyPart.contains(column) =>
        Some((key.indexName.getOrElse(column.label), true))
      case key: IndexKey if key.keyPart.contains(column) =>
        Some((key.indexName.getOrElse(column.label), false))
      case constraint: Constraint =>
        constraint.key match
          case key: (PrimaryKey & Index) if key.keyPart.contains(column) => Some(("PRIMARY", true))
          case key: (UniqueKey & Index) if key.keyPart.contains(column) =>
            Some((key.indexName.getOrElse(column.label), true))
          case _ => List.empty
      case _ => List.empty
    }

  /**
   * Methods for building and storing column information in SchemaSpy's Table model.
   *
   * @param column
   *   Trait for representing SQL Column
   * @param index
   *   The index number of the column set in the table.
   */
  private def initColumns(column: Column[?], index: Int): SchemaspyTable =
    if Option(schemaTable.getColumn(column.label)).isEmpty then
      schemaTable.getColumnsMap.put(column.label, TableColumnBuilder.build(schemaTable, column, index))

    val indexedSeq =
      (buildIndexFromColumn(column) ++ buildIndexFromKeyDefinitions(column, table.keyDefinitions)).distinct

    indexedSeq.foreach { (key, isUnique) =>
      if Option(schemaTable.getIndex(key)).isEmpty then
        val index = new TableIndex(key, isUnique)
        schemaTable.getIndexesMap.put(index.getName, index)
        index.addColumn(schemaTable.getColumn(column.label), "DESC")
    }

    column.attributes.foreach {
      case _: AutoInc[?] => schemaTable.getColumn(column.label).setIsAutoUpdated(true)
      case _             =>
    }

    detectPrimaryKeyColumn(table).map(primaryColumn => {
      schemaTable.setPrimaryColumn(TableColumnBuilder.build(schemaTable, primaryColumn, index))
      Option(schemaTable.getIndex(primaryColumn.label)).map(_.setIsPrimaryKey(true))
    })

    schemaTable

  lazy val build: SchemaspyTable =
    table.all.zipWithIndex.map((column: Column[?], index: Int) =>
      val result = initColumns(column, index)
      db.getTablesMap.put(result.getName, result)
    )

    schemaTable




© 2015 - 2024 Weber Informatics LLC | Privacy Policy