visitCreateTableStatement method

  1. @override
void visitCreateTableStatement(
  1. CreateTableStatement e,
  2. void arg
)
override

Implementation

@override
void visitCreateTableStatement(CreateTableStatement e, void arg) {
  final schemaReader =
      SchemaFromCreateTable(driftExtensions: options.useDriftExtensions);
  var hasNonGeneratedColumn = false;
  var hasPrimaryKeyDeclaration = false;
  var isStrict = false;

  if (e.isStrict) {
    if (options.version < SqliteVersion.v3_37) {
      context.reportError(AnalysisError(
        type: AnalysisErrorType.notSupportedInDesiredVersion,
        message: 'STRICT tables are only supported from sqlite3 version 37',
        relevantNode: e.strict ?? e,
      ));
    } else {
      // only report warnings related to STRICT tables if strict tables are
      // supported.
      isStrict = true;
    }
  }

  // Ensure that a table declaration only has one PRIMARY KEY constraint
  void handlePrimaryKeyNode(AstNode node) {
    if (hasPrimaryKeyDeclaration) {
      context.reportError(AnalysisError(
        type: AnalysisErrorType.duplicatePrimaryKeyDeclaration,
        message: 'Duplicate PRIMARY KEY constraint found',
        relevantNode: node,
      ));
    }
    hasPrimaryKeyDeclaration = true;
  }

  for (final column in e.columns) {
    if (isStrict) {
      final typeName = column.typeName;

      if (typeName == null) {
        // Columns in strict tables must have a type name, even if it's
        // `ANY`.
        context.reportError(AnalysisError(
          type: AnalysisErrorType.noTypeNameInStrictTable,
          message: 'In `STRICT` tables, columns must have a type name!',
          relevantNode: column.nameToken ?? column,
        ));
      } else if (!schemaReader.isValidTypeNameForStrictTable(typeName)) {
        context.reportError(AnalysisError(
          type: AnalysisErrorType.invalidTypeNameInStrictTable,
          message: 'Invalid type name for a `STRICT` table.',
          relevantNode: column.typeNames?.toSingleEntity ?? column,
        ));
      }
    }

    var isGenerated = false;

    for (final constraint in column.constraints) {
      isGenerated = isGenerated || constraint is GeneratedAs;

      if (constraint is PrimaryKeyColumn) {
        handlePrimaryKeyNode(constraint);
      }
    }

    if (!isGenerated) {
      hasNonGeneratedColumn = true;
    }
  }

  for (final constraint in e.tableConstraints) {
    if (constraint is KeyClause && constraint.isPrimaryKey) {
      handlePrimaryKeyNode(constraint);
    }
  }

  if (e.withoutRowId && !hasPrimaryKeyDeclaration) {
    context.reportError(
      AnalysisError(
        type: AnalysisErrorType.missingPrimaryKey,
        message: 'Missing PRIMARY KEY declaration for a table without rowid.',
        relevantNode: e.tableNameToken ?? e,
      ),
    );
  }

  if (!hasNonGeneratedColumn) {
    context.reportError(
      AnalysisError(
        type: AnalysisErrorType.allColumnsAreGenerated,
        message: 'This table is missing a non-generated column',
        relevantNode: e.tableNameToken ?? e,
      ),
    );
  }

  visitChildren(e, arg);
}