summaryrefslogtreecommitdiffstats
path: root/app/sql/statement.h
blob: eaaac41284c6c662c0387476163b0e7ff21614e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef APP_SQL_STATEMENT_H_
#define APP_SQL_STATEMENT_H_
#pragma once

#include <string>
#include <vector>

#include "app/sql/connection.h"
#include "base/basictypes.h"
#include "base/ref_counted.h"
#include "base/string16.h"

namespace sql {

// Possible return values from ColumnType in a statement. These should match
// the values in sqlite3.h.
enum ColType {
  COLUMN_TYPE_INTEGER = 1,
  COLUMN_TYPE_FLOAT = 2,
  COLUMN_TYPE_TEXT = 3,
  COLUMN_TYPE_BLOB = 4,
  COLUMN_TYPE_NULL = 5,
};

// Normal usage:
//   sql::Statement s(connection_.GetUniqueStatement(...));
//   if (!s)  // You should check for errors before using the statement.
//     return false;
//
//   s.BindInt(0, a);
//   if (s.Step())
//     return s.ColumnString(0);
//
// Step() and Run() just return true to signal success. If you want to handle
// specific errors such as database corruption, install an error handler in
// in the connection object using set_error_delegate().
class Statement {
 public:
  // Creates an uninitialized statement. The statement will be invalid until
  // you initialize it via Assign.
  Statement();

  explicit Statement(scoped_refptr<Connection::StatementRef> ref);
  ~Statement();

  // Initializes this object with the given statement, which may or may not
  // be valid. Use is_valid() to check if it's OK.
  void Assign(scoped_refptr<Connection::StatementRef> ref);

  // Returns true if the statement can be executed. All functions can still
  // be used if the statement is invalid, but they will return failure or some
  // default value. This is because the statement can become invalid in the
  // middle of executing a command if there is a serioud error and the database
  // has to be reset.
  bool is_valid() const { return ref_->is_valid(); }

  // These operators allow conveniently checking if the statement is valid
  // or not. See the pattern above for an example.
  operator bool() const { return is_valid(); }
  bool operator!() const { return !is_valid(); }

  // Running -------------------------------------------------------------------

  // Executes the statement, returning true on success. This is like Step but
  // for when there is no output, like an INSERT statement.
  bool Run();

  // Executes the statement, returning true if there is a row of data returned.
  // You can keep calling Step() until it returns false to iterate through all
  // the rows in your result set.
  //
  // When Step returns false, the result is either that there is no more data
  // or there is an error. This makes it most convenient for loop usage. If you
  // need to disambiguate these cases, use Succeeded().
  //
  // Typical example:
  //   while (s.Step()) {
  //     ...
  //   }
  //   return s.Succeeded();
  bool Step();

  // Resets the statement to its initial condition. This includes clearing all
  // the bound variables and any current result row.
  void Reset();

  // Returns true if the last executed thing in this statement succeeded. If
  // there was no last executed thing or the statement is invalid, this will
  // return false.
  bool Succeeded() const;

  // Binding -------------------------------------------------------------------

  // These all take a 0-based argument index and return true on failure. You
  // may not always care about the return value (they'll DCHECK if they fail).
  // The main thing you may want to check is when binding large blobs or
  // strings there may be out of memory.
  bool BindNull(int col);
  bool BindBool(int col, bool val);
  bool BindInt(int col, int val);
  bool BindInt64(int col, int64 val);
  bool BindDouble(int col, double val);
  bool BindCString(int col, const char* val);
  bool BindString(int col, const std::string& val);
  bool BindString16(int col, const string16& value);
  bool BindBlob(int col, const void* value, int value_len);

  // Retrieving ----------------------------------------------------------------

  // Returns the number of output columns in the result.
  int ColumnCount() const;

  // Returns the type associated with the given column.
  //
  // Watch out: the type may be undefined if you've done something to cause a
  // "type conversion." This means requesting the value of a column of a type
  // where that type is not the native type. For safety, call ColumnType only
  // on a column before getting the value out in any way.
  ColType ColumnType(int col) const;

  // These all take a 0-based argument index.
  bool ColumnBool(int col) const;
  int ColumnInt(int col) const;
  int64 ColumnInt64(int col) const;
  double ColumnDouble(int col) const;
  std::string ColumnString(int col) const;
  string16 ColumnString16(int col) const;

  // When reading a blob, you can get a raw pointer to the underlying data,
  // along with the length, or you can just ask us to copy the blob into a
  // vector. Danger! ColumnBlob may return NULL if there is no data!
  int ColumnByteLength(int col) const;
  const void* ColumnBlob(int col) const;
  bool ColumnBlobAsString(int col, std::string* blob);
  void ColumnBlobAsVector(int col, std::vector<char>* val) const;
  void ColumnBlobAsVector(int col, std::vector<unsigned char>* val) const;

  // Diagnostics --------------------------------------------------------------

  // Returns the original text of sql statement. Do not keep a pointer to it.
  const char* GetSQLStatement();

 private:
  // This is intended to check for serious errors and report them to the
  // connection object. It takes a sqlite error code, and returns the same
  // code. Currently this function just updates the succeeded flag, but will be
  // enhanced in the future to do the notification.
  int CheckError(int err);

  // The actual sqlite statement. This may be unique to us, or it may be cached
  // by the connection, which is why it's refcounted. This pointer is
  // guaranteed non-NULL.
  scoped_refptr<Connection::StatementRef> ref_;

  // See Succeeded() for what this holds.
  bool succeeded_;

  DISALLOW_COPY_AND_ASSIGN(Statement);
};

}  // namespace sql

#endif  // APP_SQL_STATEMENT_H_