20983 {
20985
20986 ss << "(";
20987
20988
20989 logical_index_set_t not_null_columns;
20990 logical_index_set_t unique_columns;
20991 logical_index_set_t pk_columns;
20992 unordered_set<string> multi_key_pks;
20993 vector<string> extra_constraints;
20995 if (constraint->type == ConstraintType::NOT_NULL) {
20996 auto ¬_null = constraint->Cast<NotNullConstraint>();
20997 not_null_columns.insert(not_null.index);
20998 } else if (constraint->type == ConstraintType::UNIQUE) {
20999 auto &pk = constraint->Cast<UniqueConstraint>();
21000 if (pk.HasIndex()) {
21001
21002 if (pk.IsPrimaryKey()) {
21003 pk_columns.insert(pk.GetIndex());
21004 } else {
21005 unique_columns.insert(pk.GetIndex());
21006 }
21007 } else {
21008
21009 if (pk.IsPrimaryKey()) {
21010
21011 for (auto &col : pk.GetColumnNames()) {
21012 multi_key_pks.insert(col);
21013 }
21014 }
21015 extra_constraints.push_back(constraint->ToString());
21016 }
21017 } else if (constraint->type == ConstraintType::FOREIGN_KEY) {
21018 auto &fk = constraint->Cast<ForeignKeyConstraint>();
21019 if (fk.info.type == ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE ||
21020 fk.info.type == ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE) {
21021 extra_constraints.push_back(constraint->ToString());
21022 }
21023 } else {
21024 extra_constraints.push_back(constraint->ToString());
21025 }
21026 }
21027
21028 for (
auto &column :
columns.Logical()) {
21029 if (column.Oid() > 0) {
21030 ss << ", ";
21031 }
21033 auto &column_type = column.Type();
21034 if (column_type.id() != LogicalTypeId::ANY) {
21035 ss << column.Type().ToString();
21036 }
21037 auto extra_type_info = column_type.AuxInfo();
21038 if (extra_type_info) {
21039 if (extra_type_info->type == ExtraTypeInfoType::STRING_TYPE_INFO) {
21040 auto &string_info = extra_type_info->Cast<StringTypeInfo>();
21041 if (!string_info.collation.empty()) {
21042 ss << " COLLATE " + string_info.collation;
21043 }
21044 }
21045 if (extra_type_info->type == ExtraTypeInfoType::UNBOUND_TYPE_INFO) {
21046
21047
21048
21049
21050
21051 }
21052 }
21053 bool not_null = not_null_columns.find(column.Logical()) != not_null_columns.end();
21054 bool is_single_key_pk = pk_columns.find(column.Logical()) != pk_columns.end();
21055 bool is_multi_key_pk = multi_key_pks.find(column.Name()) != multi_key_pks.end();
21056 bool is_unique = unique_columns.find(column.Logical()) != unique_columns.end();
21057 if (column.Generated()) {
21058 reference<const ParsedExpression> generated_expression = column.GeneratedExpression();
21059 if (column_type.id() != LogicalTypeId::ANY) {
21060
21061 auto &expr = generated_expression.get();
21062 D_ASSERT(expr.GetExpressionType() == ExpressionType::OPERATOR_CAST);
21063 auto &cast_expr = expr.Cast<CastExpression>();
21064 generated_expression = *cast_expr.child;
21065 }
21066 ss << " GENERATED ALWAYS AS(" << generated_expression.get().ToString() << ")";
21067 } else if (column.HasDefaultValue()) {
21068 ss << " DEFAULT(" << column.DefaultValue().ToString() << ")";
21069 }
21070 if (not_null && !is_single_key_pk && !is_multi_key_pk) {
21071
21072 ss << " NOT NULL";
21073 }
21074 if (is_single_key_pk) {
21075
21076 ss << " PRIMARY KEY";
21077 }
21078 if (is_unique) {
21079
21080 ss << " UNIQUE";
21081 }
21082 }
21083
21084 for (auto &extra_constraint : extra_constraints) {
21085 ss << ", ";
21086 ss << extra_constraint;
21087 }
21088
21089 ss << ")";
21090 return ss.str();
21091}
static string WriteOptionallyQuoted(const string &text, char quote='"', bool allow_caps = true, KeywordCategory category = KeywordCategory::KEYWORD_NONE)
Writes a string that is optionally quoted + escaped so it can be used as an identifier.
Definition duckdb.hpp:960