OS: Win 7 32bit
QT Creator 2.2.1 QT 4.7.4

I am just starting working with the ODBC driver and MSSQL. I have a basic program where I want to modify data, however I am running into the following error:
"QODBCResult::exec: unable to bind variable: "[Microsoft][ODBC SQL Server Driver]Optional feature not implemented".
This error is generated on my mapper->submit() (set in manual submit mode), when I navigate from first to next to last to previous and when I try to change data. On a data change it basically just discards the changes made and does not submit them to the model. Code is below, but the question is do I need to implement some of the "optional features" of ODBC or is there another method for using ODBC to navigate record sets?
Thanks, in advance, for your help!
AlphaWolfXV
employeeform.h
Qt Code:
  1. #ifndef EMPLOYEEFORM_H
  2. #define EMPLOYEEFORM_H
  3.  
  4. #include <QtGui>
  5. #include <QDialog>
  6. #include <QtSql>
  7. #include "../qtWidgets/recordnav/dbrecordnav.h"
  8. //tEmployees
  9. enum{
  10. tEmployee_Id = 0,
  11. tEmployee_NameCode = 1,
  12. tEmployee_FName = 2,
  13. tEmployee_LName = 3,
  14. tEmployee_DepartmentId = 4,
  15. tEmployee_StatusId = 5,
  16. tEmployee_StartDate = 6};
  17. //tDepartment Enum
  18. enum{
  19. tDepartment_Id = 0,
  20. tDepartment_Code = 1,
  21. tDepartment_Name = 2,
  22. tDepartment_Supervisor = 3,
  23. tDepartment_StatusId = 4 };
  24. //tStatus Enum
  25. enum{
  26. tStatus_Id = 0,
  27. tStatus_Desc = 1 };
  28.  
  29.  
  30. class employeeForm : public QDialog
  31. {
  32. Q_OBJECT
  33. public:
  34. employeeForm(int id,QWidget *parent = 0);
  35. private slots:
  36. void addEmployee();
  37. void deleteEmployee();
  38. void go2Prev();
  39. void go2First();
  40. void go2Last();
  41. void go2Next();
  42. void go2Rec(int a);
  43. private:
  44. QLabel *lblNameCode, *lblFName,*lblLName,*lblDept,*lblStatus, *lblStartDate;
  45. QLineEdit *leNameCode, *leFName, *leLName;
  46. QDateEdit *deStartDate;
  47. QComboBox *cbDept, *cbStatus;
  48. QPushButton *bFirst, *bPrev, *bNext, *bLast, *bAdd, *bDelete, *bClose;
  49. dbrecordnav *nav;
  50. };
  51.  
  52. #endif // EMPLOYEEFORM_H
To copy to clipboard, switch view to plain text mode 

Thanks again, and looking forward to replies!
AlphaWolfXV

employeeform.cpp
Qt Code:
  1. #include "employeeform.h"
  2.  
  3. employeeForm::employeeForm(int id, QWidget *parent)
  4. :QDialog(parent)
  5. {
  6. leNameCode = new QLineEdit;
  7. lblNameCode = new QLabel(tr("Alias"));
  8. lblNameCode->setBuddy(leNameCode);
  9. QHBoxLayout *hblNameCode = new QHBoxLayout();
  10. hblNameCode->addWidget(lblNameCode);
  11. hblNameCode->addWidget(leNameCode);
  12.  
  13. cbDept = new QComboBox;
  14. lblDept = new QLabel(tr("Department"));
  15. lblDept->setBuddy(cbDept);
  16. QHBoxLayout *hblDept = new QHBoxLayout();
  17. hblDept->addWidget(lblDept);
  18. hblDept->addWidget(cbDept);
  19.  
  20. leFName = new QLineEdit;
  21. lblFName = new QLabel(tr("First Name:"));
  22. lblFName->setBuddy(leFName);
  23. QHBoxLayout *hblName = new QHBoxLayout();
  24. hblName->addWidget(lblFName);
  25. hblName->addWidget(leFName);
  26. hblName->addSpacing(20);
  27.  
  28. leLName = new QLineEdit;
  29. lblLName = new QLabel(tr("Last Name:"));
  30. lblLName->setBuddy(leLName);
  31. hblName->addWidget(lblLName);
  32. hblName->addWidget(leLName);
  33.  
  34. cbStatus = new QComboBox;
  35. lblStatus = new QLabel(tr("Employment Status:"));
  36. lblStatus->setBuddy(cbStatus);
  37. QHBoxLayout *hblStatus = new QHBoxLayout();
  38. hblStatus->addWidget(lblStatus);
  39. hblStatus->addWidget(cbStatus);
  40.  
  41. deStartDate = new QDateEdit;
  42. deStartDate->setCalendarPopup(true);
  43. QDate today = QDate::currentDate();
  44. deStartDate->setDateRange(today.addDays(-90),today.addDays(90));
  45. deStartDate->setDate(today);
  46. lblStartDate = new QLabel(tr("Start Date:"));
  47. lblStartDate->setBuddy(deStartDate);
  48. QHBoxLayout *hblStartDate = new QHBoxLayout();
  49. hblStartDate->addWidget(lblStartDate);
  50. hblStartDate->addWidget(deStartDate);
  51.  
  52. bClose = new QPushButton("&Close");
  53.  
  54. //finally lets set up the model
  55. tableModel = new QSqlRelationalTableModel(this);
  56. tableModel->setTable("tEmp");
  57. tableModel->setRelation(tEmployee_DepartmentId, QSqlRelation("tDepartment","idtDepartment","tDepartment_Name"));
  58. tableModel->setRelation(tEmployee_StatusId,QSqlRelation("tStatus","idtStatus","tStatus_Code"));
  59. tableModel->setEditStrategy(QSqlTableModel::OnRowChange);
  60. //tableModel->setSort(tEmployee_NameCode,Qt::AscendingOrder);
  61. tableModel->select();
  62.  
  63. //uses the relation set earlier when setRelation() was called.
  64. //because of this, we cannot just use the table enums to get the model row, they may be different
  65.  
  66. QSqlTableModel *relationModel = tableModel->relationModel(tEmployee_DepartmentId);
  67. cbDept->setModel(relationModel);
  68. cbDept->setModelColumn(relationModel->fieldIndex("tDepartment_Name"));//cbDept->setModelColumn(tDepartment_Name);
  69. QSqlTableModel *relationModel_status = tableModel->relationModel(tEmployee_StatusId);
  70. cbStatus->setModel(relationModel_status);
  71. cbStatus->setModelColumn(relationModel_status->fieldIndex("tStatus_Code"));//cbStatus->setModelColumn(tStatus_Desc);
  72.  
  73. //now we can map the records from the database into the form...
  74. mapper = new QDataWidgetMapper(this);
  75. mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
  76. mapper->setModel(tableModel);
  77. mapper->setItemDelegate(new QSqlRelationalDelegate(this));
  78. mapper->addMapping(leNameCode, tEmployee_NameCode);
  79. mapper->addMapping(leFName,tEmployee_FName);
  80. mapper->addMapping(leLName,tEmployee_LName);
  81. mapper->addMapping(cbDept, tEmployee_DepartmentId);
  82. mapper->addMapping(deStartDate,tEmployee_StartDate);
  83. mapper->addMapping(cbStatus,tEmployee_StatusId);
  84.  
  85. //finally now if the form was called with a valid id, then populated with that Ids records...
  86. //otherwise just use the first record ...
  87. if(id != -1)
  88. {
  89. for(int row = 0; row < tableModel->rowCount(); ++row)
  90. {
  91. QSqlRecord record = tableModel->record(row);
  92. if(record.value(tEmployee_Id).toInt() == id)
  93. {
  94. mapper->setCurrentIndex(row);
  95. break;
  96. }
  97. }
  98. }
  99. else
  100. mapper->toFirst();
  101.  
  102. nav = new dbrecordnav(this);
  103. nav->setCurrentRec(mapper->currentIndex()+1);
  104. nav->setTotalRec(tableModel->rowCount());
  105.  
  106. QVBoxLayout *vblMain = new QVBoxLayout();
  107. vblMain->addLayout(hblNameCode);
  108. vblMain->addLayout(hblDept);
  109. vblMain->addLayout(hblName);
  110. vblMain->addLayout(hblStartDate);
  111. vblMain->addLayout(hblStatus);
  112. vblMain->addWidget(nav);
  113. setLayout(vblMain);
  114.  
  115. //finally connect statements
  116. connect(nav,SIGNAL(first()),this,SLOT(go2First()));
  117. connect(nav,SIGNAL(prev()),this,SLOT(go2Prev()));
  118. connect(nav,SIGNAL(next()),this,SLOT(go2Next()));
  119. connect(nav,SIGNAL(last()),this,SLOT(go2Last()));
  120. connect(nav,SIGNAL(newrec()),this,SLOT(addEmployee()));
  121. connect(nav,SIGNAL(deleterec()),this,SLOT(deleteEmployee()));
  122. connect(nav,SIGNAL(changeRecord(int)),this,SLOT(go2Rec(int)));
  123. connect(bClose,SIGNAL(clicked()),this,SLOT(close()));
  124. }
  125. void employeeForm::go2First()
  126. {
  127. int row = mapper->currentIndex();
  128. if(! mapper->submit())
  129. {
  130. qDebug()<<"go2first//lasterror:"<<tableModel->lastError().text();
  131. tableModel->revertAll();
  132. }
  133. mapper->toFirst();
  134. nav->setCurrentRec(mapper->currentIndex()+1);
  135. nav->setTotalRec(tableModel->rowCount());
  136. }
  137. void employeeForm::go2Prev()
  138. {
  139. int row = mapper->currentIndex();
  140. if(! mapper->submit())
  141. {
  142. qDebug()<<"go2prev//lasterror:"<<tableModel->lastError().text();
  143. tableModel->revertRow(row);
  144. }
  145. if(row > 0)
  146. row--;
  147. mapper->setCurrentIndex(row);
  148.  
  149. nav->setCurrentRec(mapper->currentIndex()+1);
  150. nav->setTotalRec(tableModel->rowCount());
  151. }
  152. void employeeForm::go2Next()
  153. {
  154. int row = mapper->currentIndex();
  155. if(!mapper->submit())
  156. {
  157. qDebug()<<"go2next//lasterror:"<<tableModel->lastError().text();
  158. tableModel->revertRow(row);
  159. }
  160.  
  161. mapper->setCurrentIndex(row);
  162. mapper->toNext();
  163. nav->setCurrentRec(mapper->currentIndex()+1);
  164. nav->setTotalRec(tableModel->rowCount());
  165. }
  166. void employeeForm::go2Last()
  167. {
  168. int row = mapper->currentIndex();
  169. if(!mapper->submit())
  170. {
  171. qDebug()<<"go2last//lasterror:"<<tableModel->lastError().text();
  172. tableModel->revertRow(row);
  173. row--;
  174. }
  175. mapper->setCurrentIndex(row);
  176. mapper->toLast();
  177. nav->setCurrentRec(mapper->currentIndex()+1);
  178. nav->setTotalRec(tableModel->rowCount());
  179. }
  180.  
  181. void employeeForm::go2Rec(int a)
  182. {
  183. if((a-1) <= tableModel->rowCount())
  184. mapper->setCurrentIndex(a-1);
  185. else
  186. {
  187. mapper->toLast();
  188. nav->setCurrentRec(mapper->currentIndex()+1);
  189. nav->setTotalRec(tableModel->rowCount());
  190. }
  191. }
  192. void employeeForm::addEmployee()
  193. {
  194. //add records at the end of the list
  195. //mapper->submit();
  196. mapper->toLast();
  197. int row = mapper->currentIndex();
  198. qDebug()<<"Row Num" << row;
  199. tableModel->insertRow(row+1);
  200. qDebug()<<"After Insert Row";
  201. mapper->setCurrentIndex(row+1);
  202. qDebug()<<"After set Curret Index.";
  203. //set the nav counts up 1
  204. nav->setCurrentRec(mapper->currentIndex()+1);
  205. nav->setTotalRec(tableModel->rowCount());
  206. leNameCode->clear();
  207. leFName->clear();
  208. leLName->clear();
  209. cbDept->clear();
  210. cbStatus->clear();
  211. deStartDate->setDate(QDate::currentDate());
  212. leNameCode->setFocus();
  213. }
  214. void employeeForm::deleteEmployee()
  215. {
  216. int row = mapper->currentIndex();
  217. tableModel->removeRow(row);
  218. mapper->submit();
  219. mapper->setCurrentIndex(qMin(row,tableModel->rowCount()-1));
  220. nav->setCurrentRec(mapper->currentIndex()+1);
  221. nav->setTotalRec(tableModel->rowCount());
  222. }
To copy to clipboard, switch view to plain text mode