THRIFT-3339 Support for database/sql
Client: Go
Patch: Adam Beberg <beberg@sentient.ai>
Contributed by Sentient Technologies - http://www.sentient.ai/
This closes #623
diff --git a/compiler/cpp/src/generate/t_go_generator.cc b/compiler/cpp/src/generate/t_go_generator.cc
index f04bc48..3e6cdbd 100644
--- a/compiler/cpp/src/generate/t_go_generator.cc
+++ b/compiler/cpp/src/generate/t_go_generator.cc
@@ -247,9 +247,9 @@
std::string go_autogen_comment();
std::string go_package();
- std::string go_imports_begin();
+ std::string go_imports_begin(bool ttypes);
std::string go_imports_end();
- std::string render_includes();
+ std::string render_includes(bool ttypes);
std::string render_import_protection();
std::string render_fastbinary_includes();
std::string declare_argument(t_field* tfield);
@@ -756,18 +756,19 @@
}
// Print header
- f_types_ << go_autogen_comment() << go_package() << render_includes()
+ f_types_ << go_autogen_comment() << go_package() << render_includes(true)
<< render_import_protection();
- f_consts_ << go_autogen_comment() << go_package() << render_includes();
+ f_consts_ << go_autogen_comment() << go_package() << render_includes(false);
f_const_values_ << endl << "func init() {" << endl;
}
/**
- * Renders all the imports necessary for including another Thrift program
+ * Renders all the imports necessary for including another Thrift program.
+ * If ttypes include the additional imports for ttypes.go.
*/
-string t_go_generator::render_includes() {
+string t_go_generator::render_includes(bool ttypes) {
const vector<t_program*>& includes = program_->get_includes();
string result = "";
string unused_prot = "";
@@ -791,7 +792,7 @@
result += "\n";
}
- return go_imports_begin() + result + go_imports_end() + unused_prot;
+ return go_imports_begin(ttypes) + result + go_imports_end() + unused_prot;
}
string t_go_generator::render_import_protection() {
@@ -823,12 +824,21 @@
}
/**
- * Render the beginning of the import statement
+ * Render the beginning of the import statement.
+ * If ttypes include the additional imports for ttypes.go.
*/
-string t_go_generator::go_imports_begin() {
+string t_go_generator::go_imports_begin(bool ttypes) {
+ string extra;
+ // If writing ttypes.go, and there are enums, need extra imports.
+ if (ttypes && get_program()->get_enums().size() > 0) {
+ extra =
+ "\t\"database/sql/driver\"\n"
+ "\t\"errors\"\n";
+ }
return string(
"import (\n"
"\t\"bytes\"\n"
+ + extra +
"\t\"fmt\"\n"
"\t\"" + gen_thrift_import_ + "\"\n");
}
@@ -955,6 +965,21 @@
f_types_ << "if (err != nil) {" << endl << "return err" << endl << "}" << endl;
f_types_ << "*p = q" << endl;
f_types_ << "return nil" << endl;
+ f_types_ << "}" << endl << endl;
+
+ // Generate Scan for sql.Scanner interface
+ f_types_ << "func (p *" << tenum_name << ") Scan(value interface{}) error {" <<endl;
+ f_types_ << "v, ok := value.(int64)" <<endl;
+ f_types_ << "if !ok {" <<endl;
+ f_types_ << "return errors.New(\"Scan value is not int64\")" <<endl;
+ f_types_ << "}" <<endl;
+ f_types_ << "*p = " << tenum_name << "(v)" << endl;
+ f_types_ << "return nil" << endl;
+ f_types_ << "}" << endl << endl;
+
+ // Generate Value for driver.Valuer interface
+ f_types_ << "func (p " << tenum_name << ") Value() (driver.Value, error) {" <<endl;
+ f_types_ << "return int64(p), nil" << endl;
f_types_ << "}" << endl;
}
@@ -1219,19 +1244,20 @@
t_type* fieldType = (*m_iter)->get_type();
string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter));
- string gotag;
+ string gotag = "db:\"" + escape_string((*m_iter)->get_name()) + "\" ";
if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
- gotag = "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\"";
+ gotag += "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\"";
} else {
- gotag = "json:\"" + escape_string((*m_iter)->get_name()) + "\"";
+ gotag += "json:\"" + escape_string((*m_iter)->get_name()) + "\"";
}
+
+ // Check for user override of db and json tags using "go.tag"
std::map<string, string>::iterator it = (*m_iter)->annotations_.find("go.tag");
if (it != (*m_iter)->annotations_.end()) {
gotag = it->second;
}
indent(out) << publicize((*m_iter)->get_name()) << " " << goType << " `thrift:\""
<< escape_string((*m_iter)->get_name()) << "," << sorted_keys_pos;
-
if ((*m_iter)->get_req() == t_field::T_REQUIRED) {
out << ",required";
}
@@ -1653,7 +1679,7 @@
f_service_name = package_dir_ + "/" + filename + ".go";
}
f_service_.open(f_service_name.c_str());
- f_service_ << go_autogen_comment() << go_package() << render_includes();
+ f_service_ << go_autogen_comment() << go_package() << render_includes(false);
generate_service_interface(tservice);
generate_service_client(tservice);