Feature #12167
openEnable setting of a Default Value for Dbo fields
0%
Description
Adding this would enable automatic update for Tables that already have Data
I Build a "Wt" Way to update SQL Tables in which I scan the generated SQL against previous versions. Then I remove all colums of a table that are already present in the older ones.
The Rest can be added with strict sql and as long as the table is empty, everything works.
If new columns are set as optional, this also works.
But as soon as the first row is filled in, updating failed as no default is given.
Adding a default, that shows up in the sql would fix that immediately =)
This might also help with generating info about the Application or Module Version to then update older info with new elements if needed.
Thanks
Updated by Matthias Van Ceulebroeck 12 months ago
- Target version set to future
Hello Christian,
I see your use-case. This is, however, a big undertaking, as it touches a lot of code. I will schedule this for the future, and still under some reservation.
For now, I would advise some external system to manage your database (structure). I have used flyway before, and think that's fairly decent. I know Liquibase is an alternative to it, but have never used it. That way you can define your structure very clearly, and perform migrations on it.
Additionally, this has the advantage that it provides more control in that you can define things not possible in Wt (like indexes for example).
Updated by Christian Meyer 3 months ago
Tried it and for now it seems to work
Added new Dbo::field()
overload that takes a "default Value" as first parameter as a string to avoid ambiguity
Added new Constructor for FieldRef and FieldInfo
updated createTable to add default Value when exists
Here is a Diff
Would love some feedback if possible
Cheers
Christian
diff --git a/src/Wt/Dbo/DbAction_impl.h b/src/Wt/Dbo/DbAction_impl.h
index 7671812e..306b7bce 100644
--- a/src/Wt/Dbo/DbAction_impl.h
+++ b/src/Wt/Dbo/DbAction_impl.h
@@ -91,9 +91,17 @@ void InitSchema::act(const FieldRef<V>& field)
foreignKeyTable_, foreignKeyName_,
flags | FieldFlags::ForeignKey, fkConstraints_));
else
- // Normal field
- mapping_.fields.push_back
- (FieldInfo(field.name(), &typeid(V), field.sqlType(session_), flags));
+ {
+ if(field.hasDefaultValue())
+ {
+ mapping_.fields.push_back
+ (FieldInfo(field.name(), &typeid(V), field.sqlType(session_), flags, field.defaultValue()));
+
+ }else
+ // Normal field
+ mapping_.fields.push_back
+ (FieldInfo(field.name(), &typeid(V), field.sqlType(session_), flags));
+ }
}
template<class C>
diff --git a/src/Wt/Dbo/Field.h b/src/Wt/Dbo/Field.h
index 8b1b0f94..2fe40104 100644
--- a/src/Wt/Dbo/Field.h
+++ b/src/Wt/Dbo/Field.h
@@ -182,7 +182,8 @@ public:
AuxId = 0x1
};
- FieldRef(V& value, const std::string& name, int size, int flags = 0);
+ explicit FieldRef(V& value, const std::string& name, int size, int flags = 0);
+ explicit FieldRef(const std::string& defaultValue, V& value, const std::string& name, int size, int flags = 0);
const std::string& name() const;
int size() const;
@@ -193,6 +194,9 @@ public:
const V& value() const { return value_; }
void setValue(const V& value) const { value_ = value; }
+ bool hasDefaultValue() const { return hasDefaultValue_; }
+ const std::string& defaultValue() const { return defaultValue_; }
+
void bindValue(SqlStatement *statement, int column) const;
void setValue(Session& session, SqlStatement *statement, int column) const;
@@ -201,6 +205,8 @@ private:
std::string name_;
int size_;
int flags_;
+ bool hasDefaultValue_ = false;
+ std::string defaultValue_ = {};
};
/*! \brief Type of an SQL relation.
@@ -368,6 +374,9 @@ void auxId(Action& action, ptr<C>& value, const std::string& name,
template <class Action, typename V>
void field(Action& action, V& value, const std::string& name, int size = -1);
+template <class Action, typename V>
+void field(const std::string& defaultValue, Action& action, V& value, const std::string& name, int size = -1);
+
/*
* This is synonym for belongsTo(), and used by id(). We should overload
* this method also to allow foreign key constraints.
diff --git a/src/Wt/Dbo/Field_impl.h b/src/Wt/Dbo/Field_impl.h
index 51318323..ab02de21 100644
--- a/src/Wt/Dbo/Field_impl.h
+++ b/src/Wt/Dbo/Field_impl.h
@@ -24,6 +24,15 @@ FieldRef<V>::FieldRef(V& value, const std::string& name, int size, int flags)
flags_(flags)
{ }
+template <typename V>
+FieldRef<V>::FieldRef(const std::string& dValue, V& value, const std::string& name, int size, int flags)
+ : value_(value),
+ name_(name),
+ size_(size),
+ flags_(flags),
+ defaultValue_(dValue)
+{ }
+
template <typename V>
const std::string& FieldRef<V>::name() const
{
@@ -204,6 +213,12 @@ void field(A& action, V& value, const std::string& name, int size)
action.act(FieldRef<V>(value, name, size));
}
+template <class A, typename V>
+void field(const std::string& dValue, A& action, V& value, const std::string& name, int size)
+{
+ action.act(FieldRef<V>(dValue, value, name, size));
+}
+
template <class A, class C>
void field(A& action, ptr<C>& value, const std::string& name, int)
{
diff --git a/src/Wt/Dbo/Session.C b/src/Wt/Dbo/Session.C
index 530a247c..70de9a7b 100644
--- a/src/Wt/Dbo/Session.C
+++ b/src/Wt/Dbo/Session.C
@@ -786,6 +786,11 @@ void Session::createTable(Impl::MappingInfo *mapping,
sql << " \"" << field.name() << "\" " << sqlType;
+ if(field.hasDefaultValue())
+ {
+ sql << " DEFAULT " << field.sqlDefaultValue();
+ }
+
firstField = false;
if (field.isNaturalIdField()) {
diff --git a/src/Wt/Dbo/SqlTraits.C b/src/Wt/Dbo/SqlTraits.C
index 8ce64afe..0aab719d 100644
--- a/src/Wt/Dbo/SqlTraits.C
+++ b/src/Wt/Dbo/SqlTraits.C
@@ -29,6 +29,19 @@ FieldInfo::FieldInfo(const std::string& name,
flags_(flags)
{ }
+FieldInfo::FieldInfo(const std::string& name,
+ const std::type_info *type,
+ const std::string& sqlType,
+ int flags,
+ const std::string& defaultValue)
+ : name_(name),
+ sqlType_(sqlType),
+ type_(type),
+ flags_(flags),
+ sqlDefaultValue_(defaultValue),
+ hasDefaultValue_(true)
+{ }
+
FieldInfo::FieldInfo(const std::string& name, const std::type_info *type,
const std::string& sqlType,
const std::string& foreignKeyTable,
diff --git a/src/Wt/Dbo/SqlTraits.h b/src/Wt/Dbo/SqlTraits.h
index 8803f314..354713b5 100644
--- a/src/Wt/Dbo/SqlTraits.h
+++ b/src/Wt/Dbo/SqlTraits.h
@@ -196,6 +196,11 @@ public:
FieldInfo(const std::string& name, const std::type_info *type,
const std::string& sqlType, int flags);
+ /*! \brief Creates a field description.
+ */
+ FieldInfo(const std::string& name, const std::type_info *type,
+ const std::string& sqlType, int flags, const std::string& defaultValue);
+
/*! \brief Creates a field description.
*/
FieldInfo(const std::string& name, const std::type_info *type,
@@ -216,6 +221,14 @@ public:
*/
const std::string& sqlType() const { return sqlType_; }
+ /*! \brief Returns the default SQL Value.
+ */
+ const std::string& sqlDefaultValue() const { return sqlDefaultValue_; }
+
+ /*! \brief Returns whether there is a default SQL Value.
+ */
+ const bool hasDefaultValue() const { return hasDefaultValue_; }
+
/*! \brief Returns the field qualifier.
*/
const std::string& qualifier() const { return qualifier_; }
@@ -263,11 +276,12 @@ public:
std::string sql() const;
private:
- std::string name_, sqlType_, qualifier_;
+ std::string name_, sqlType_, qualifier_, sqlDefaultValue_ = "";
std::string foreignKeyName_, foreignKeyTable_;
const std::type_info *type_;
int flags_;
int fkConstraints_;
+ bool hasDefaultValue_ = false;
};
/*! \class query_result_traits Wt/Dbo/SqlTraits.h Wt/Dbo/SqlTraits.h