Tianchi  v0.0.2 build 20130701
C++ library for Qt with VC & mingW
tcdataaccess.h
1 #ifndef TIANCHI_TCDATAACCESS_H
2 #define TIANCHI_TCDATAACCESS_H
3 
4 #include <tianchi/tcglobal.h>
5 
6 #include <QString>
7 #include <QLatin1String>
8 #include <QVariant>
9 #include <QSqlQuery>
10 #include <QSqlRecord>
11 #include <QSqlDatabase>
12 #include <QVariantMap>
13 #include <QStringList>
14 #include <QVariantList>
15 
16 class TcDataAccess;
17 
18 // 数据访问语句类
19 class TIANCHI_API TcDataAccessStatement
20 {
21 public:
24  // 使用表名table和字段列表fields初始化
25  TcDataAccessStatement(const QString &table,
26  const QString &fields = QString("*"));
28 
29  // 清除所有设定
30  void clear();
31 
32  // 添加字段列表fields
33  TcDataAccessStatement& select(const QString &fields = QString("*"));
34 
35  // 添加from表名tables
36  TcDataAccessStatement& from(const QString &tables);
37 
38  // 增加左连接表table, cond为条件,bind为条件中的"?"值
39  TcDataAccessStatement& leftJoin(const QString &table,
40  const QString &cond,
41  const QVariantList &bind = QVariantList());
42 
43  // 增加条件子句expr(AND连接), bind为条件中的"?"值
44  TcDataAccessStatement& where(const QString &expr,
45  const QVariantList &bind = QVariantList());
46 
47  // 增加条件子句expr(OR连接), bind为条件中的"?"值
48  TcDataAccessStatement& orWhere(const QString &expr,
49  const QVariantList &bind = QVariantList());
50 
51  // 增加group字段fields
52  TcDataAccessStatement& group(const QString &fields);
53 
54  // 增加order字段fields
55  TcDataAccessStatement& order(const QString &fields);
56 
57  // 增加limit限制
58  TcDataAccessStatement& limit(int count, int offset = 0);
59 
60  // 增加limit限制
61  TcDataAccessStatement& limitPage(int page, int rowCount);
62 
63  // 返回完整的SQL语句
64  QString toString() const;
65 
66  // 返回WHERE子句
67  QString whereString() const;
68 
69  // 返回WHERE中"?"的bind
70  QVariantList whereBind() const;
71 
72  // 返回所有"?"的bind
73  QVariantList bind() const;
74 
75  TcDataAccessStatement& operator=(const TcDataAccessStatement &da);
76 private:
77  QStringList _select;
78  QStringList _from;
79  QStringList _leftJoin;
80  QStringList _where;
81  QStringList _group;
82  QStringList _order;
83 
84  QString _limit;
85  QVariantList _leftJoinBind;
86  QVariantList _whereBind;
87 };
88 
89 
90 // 数据访问类
91 class TIANCHI_API TcDataAccess
92 {
93 public:
94  enum AttrCase
95  {
96  CaseNatural, // 字段名保存不变
97  CaseLower, // 字段名转为小写
98  CaseUpper // 字段名转为大写
99  };
100 
101  enum AttrTrim
102  {
103  TrimNone, // 保持字符串类型字段值不变
104  TrimAll // 保持字符串类型字段值去除前后空格
105  };
106 
107  TcDataAccess(const QString &connectionName
108  = QLatin1String(QSqlDatabase::defaultConnection));
109  TcDataAccess(const QSqlDatabase &other);
110  ~TcDataAccess();
111 
112  // 返回字段名处理方式
113  static AttrCase attrCase() {return _attrCase;}
114  // 返回字符串类型字段值处理方式
115  static AttrTrim attrTrim() {return _attrTrim;}
116  // 设置字段名处理方式
117  static void setAttrCase(AttrCase attrCase){_attrCase = attrCase;}
118  // 设置字符串类型字段值处理方式
119  static void setAttrTrim(AttrTrim attrTrim){_attrTrim = attrTrim;}
120 
121  // 创建一个DataAccess对象,如果创建失败,返回NULL,使用完后请delete
122  static TcDataAccess* db(const QString &connectionName
123  = QLatin1String(QSqlDatabase::defaultConnection));
124 
125  // 返回connectionName
126  QString connectionName() const {return _db->connectionName();}
127 
128  // 返回QSqlQuery对象
129  QSqlQuery sqlQuery() const {return QSqlQuery(*_db);}
130  // 返回QSqlDatabase对象
131  QSqlDatabase sqlDatabase() const {return *_db;}
132 
133  // 返回sql查询的所有记录集
134  QList<QVariantMap> fetchAll(const QString &sql,
135  const QVariantList &bind = QVariantList());
136  QList<QVariantMap> fetchAll(const TcDataAccessStatement &stat,
137  const QVariantList &bind = QVariantList());
138 
139  // 返回SQL查询的所有记录集,
140  // 如果有记录,则第一行保存字段名,记录从第二行开始
141  QList<QVariantList> fetchAllList(const QString &sql,
142  const QVariantList &bind = QVariantList());
143  QList<QVariantList> fetchAllList(const TcDataAccessStatement &stat,
144  const QVariantList &bind = QVariantList());
145 
146 
147  // 返回sql查询的第一行
148  QVariantMap fetchRow(const QString &sql,
149  const QVariantList &bind = QVariantList());
150  QVariantMap fetchRow(const TcDataAccessStatement &stat,
151  const QVariantList &bind = QVariantList());
152 
153 
154  // 返回sql查询的第一列
155  QVariantList fetchCol(const QString &sql,
156  const QVariantList &bind = QVariantList());
157  QVariantList fetchCol(const TcDataAccessStatement &stat,
158  const QVariantList &bind = QVariantList());
159 
160  // 返回第一行第一列数据
161  QVariant fetchOne(const QString &sql,
162  const QVariantList &bind = QVariantList());
163  QVariant fetchOne(const TcDataAccessStatement &stat,
164  const QVariantList &bind = QVariantList());
165 
166  // 将第一列作为key,将第二列作为值返回
167  template <typename T> QMap<T, QVariant> fetchPairs(
168  const QString &sql,
169  const QVariantList &bind = QVariantList())
170  {
171  _prepareExec(sql, bind);
172 
173  QMap<T,QVariant> rows;
174  while (_query->next())
175  {
176  rows[qvariant_cast<T>(_trim(_query->value(0)))] =
177  _trim(_query->value(1));
178  }
179  return rows;
180  }
181 
182  template <typename T> QMap<T, QVariant> fetchPairs(
183  const TcDataAccessStatement &stat,
184  const QVariantList &bind = QVariantList())
185  {
186  return fetchPairs<T>(stat.toString(),
187  QVariantList() << stat.bind() << bind);
188  }
189 
190  // 将第一列作为键,将每行作为值返回
191  template <typename T> QMap<T, QVariantMap> fetchAssoc(
192  const QString &sql,
193  const QVariantList &bind = QVariantList())
194  {
195  _prepareExec(sql, bind);
196 
197  QMap<T,QVariantMap> rows;
198  QVariantMap row;
199  QVariant val;
200  while (_query->next())
201  {
202  QSqlRecord rec = _query->record();
203  for (int i = rec.count() - 1; i > -1; i--)
204  {
205  row[_case(rec.fieldName(i))] = _trim(rec.value(i));
206  }
207  rows[qvariant_cast<T>(_trim(rec.value(0)))] = row;
208  row.clear();
209  }
210  return rows;
211  }
212 
213  template <typename T> QMap<T, QVariantMap> fetchAssoc(
214  const TcDataAccessStatement &stat,
215  const QVariantList &bind = QVariantList())
216  {
217  return fetchAssoc<T>(stat.toString(),
218  QVariantList() << stat.bind() << bind);
219  }
220 
221  // 为sql语句添加limit参数,目前只支持MySQL、PGSQL、SQLite、MSSQL,对于不支持
222  // 的数据库类型,直接返回空字符串
223  QString limitPage(const QString &sql, int page, int rowCount) const;
224  QString limit(const QString &sql, int count, int offset = 0) const;
225 
226  // 返回上次插入的ID,目前的实现无意义
227  QVariant lastInsertId(const QString &table = QString(),
228  const QString &primaryKey = QString()) const;
229  // 返回上次查询的错误信息
230  QSqlError lastError() const;
231 
232  // 删除表table中的记录,条件为where, bind为"?"绑定
233  int doDelete(const QString &table,
234  const QString &where = QString(),
235  const QVariantList &bind = QVariantList());
236 
237 
238  // 更新表table中的记录,字段及值为field, 条件为where, bind为"?"绑定
239  int doUpdate(const QString &table, const QVariantMap &field,
240  const QString &where = QString(),
241  const QVariantList &bind = QVariantList());
242 
243  // 插入表table中的记录,字段及值为field
244  int doInsert(const QString &table, const QVariantMap &field);
245  TcDataAccess& operator=(const TcDataAccess &da);
246  TcDataAccess& operator=(const QSqlDatabase &db);
247 private:
248  QVariant _trim(const QVariant &val);
249  QString _case(const QString &field);
250 private:
251  static AttrCase _attrCase;
252  static AttrTrim _attrTrim;
253  QSqlDatabase *_db;
254  QSqlQuery *_query;
255  void _prepareExec(const QString &sql, const QVariantList &bind);
256 };
257 
258 typedef TcDataAccess TcDA;
260 
261 #endif