~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to gears/base/common/position_table.cc

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2008, Google Inc.
 
2
//
 
3
// Redistribution and use in source and binary forms, with or without
 
4
// modification, are permitted provided that the following conditions are met:
 
5
//
 
6
//  1. Redistributions of source code must retain the above copyright notice,
 
7
//     this list of conditions and the following disclaimer.
 
8
//  2. Redistributions in binary form must reproduce the above copyright notice,
 
9
//     this list of conditions and the following disclaimer in the documentation
 
10
//     and/or other materials provided with the distribution.
 
11
//  3. Neither the name of Google Inc. nor the names of its contributors may be
 
12
//     used to endorse or promote products derived from this software without
 
13
//     specific prior written permission.
 
14
//
 
15
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
16
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
17
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
18
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
19
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
20
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
21
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
22
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
23
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
24
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 
 
26
#include "gears/base/common/position_table.h"
 
27
 
 
28
// Macros for use in SQL statements.
 
29
#define POSITION L"Position"
 
30
#define NAME L"Name"
 
31
 
 
32
// Database schema.
 
33
static const char *kCreateTableVersion1Statement =
 
34
    "CREATE TABLE Position ("
 
35
    " Name TEXT PRIMARY KEY, "
 
36
    " Latitude DOUBLE NOT NULL, "
 
37
    " Longitude DOUBLE NOT NULL, "
 
38
    " Altitude INTEGER NOT NULL, "
 
39
    " Accuracy INTEGER NOT NULL, "
 
40
    " AltitudeAccuracy INTEGER NOT NULL, "
 
41
    " Timestamp INT64 NOT NULL, "
 
42
    " StreetNumber TEXT NOT NULL, "
 
43
    " Street TEXT NOT NULL, "
 
44
    " Premises TEXT NOT NULL, "
 
45
    " City TEXT NOT NULL, "
 
46
    " County TEXT NOT NULL, "
 
47
    " Region TEXT NOT NULL, "
 
48
    " Country TEXT NOT NULL, "
 
49
    " CountryCode TEXT NOT NULL, "
 
50
    " PostalCode TEXT NOT NULL, "
 
51
    " ErrorCode INTEGER NOT NULL, "
 
52
    " ErrorMessage TEXT NOT NULL "
 
53
    ")";
 
54
 
 
55
PositionTable::PositionTable(SQLDatabase *db) : db_(db) {
 
56
}
 
57
 
 
58
bool PositionTable::CreateTableLatestVersion() {
 
59
  return CreateVersion1();
 
60
}
 
61
 
 
62
bool PositionTable::SetPosition(const std::string16 &name,
 
63
                                const Position &position) {
 
64
// Local helper macro.
 
65
#define LOG_BIND_ERROR(name) \
 
66
    LOG(("PositionTable::SetPosition unable to bind " name ": %d.\n", \
 
67
    db_->GetErrorCode()));
 
68
 
 
69
  SQLTransaction transaction(db_, "PositionTable::SetPosition");
 
70
  if (!transaction.Begin()) {
 
71
    return false;
 
72
  }
 
73
 
 
74
  const char16 *sql = STRING16(L"REPLACE INTO " POSITION L" "
 
75
                               L"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
 
76
                               L"?, ?, ?, ?, ?, ?)");
 
77
 
 
78
  SQLStatement statement;
 
79
  if (SQLITE_OK != statement.prepare16(db_, sql)) {
 
80
    LOG(("PositionTable::SetPosition unable to prepare: %d.\n",
 
81
         db_->GetErrorCode()));
 
82
    return false;
 
83
  }
 
84
 
 
85
  if (SQLITE_OK != statement.bind_text16(0, name.c_str())) {
 
86
    LOG_BIND_ERROR("name");
 
87
    return false;
 
88
  }
 
89
  if (SQLITE_OK != statement.bind_double(1, position.latitude)) {
 
90
    LOG_BIND_ERROR("latitude");
 
91
    return false;
 
92
  }
 
93
  if (SQLITE_OK != statement.bind_double(2, position.longitude)) {
 
94
    LOG_BIND_ERROR("longitude");
 
95
    return false;
 
96
  }
 
97
  // The Altitude, Accuracy and AltitudeAccuracy columns have type INTEGER, but
 
98
  // we can safely store and extract floating point values because SQLite uses
 
99
  // type affinity. See http://www.sqlite.org/datatype3.html#affinity.
 
100
  if (SQLITE_OK != statement.bind_double(3, position.altitude)) {
 
101
    LOG_BIND_ERROR("altitude");
 
102
    return false;
 
103
  }
 
104
  if (SQLITE_OK != statement.bind_double(4, position.accuracy)) {
 
105
    LOG_BIND_ERROR("accuracy");
 
106
    return false;
 
107
  }
 
108
  if (SQLITE_OK != statement.bind_double(5, position.altitude_accuracy)) {
 
109
    LOG_BIND_ERROR("altitude accuracy");
 
110
    return false;
 
111
  }
 
112
  if (SQLITE_OK != statement.bind_int64(6, position.timestamp)) {
 
113
    LOG_BIND_ERROR("timestamp");
 
114
    return false;
 
115
  }
 
116
  if (SQLITE_OK !=
 
117
      statement.bind_text16(7, position.address.street_number.c_str())) {
 
118
    LOG_BIND_ERROR("street number");
 
119
    return false;
 
120
  }
 
121
  if (SQLITE_OK != statement.bind_text16(8, position.address.street.c_str())) {
 
122
    LOG_BIND_ERROR("street");
 
123
    return false;
 
124
  }
 
125
  if (SQLITE_OK !=
 
126
      statement.bind_text16(9, position.address.premises.c_str())) {
 
127
    LOG_BIND_ERROR("premises");
 
128
    return false;
 
129
  }
 
130
  if (SQLITE_OK != statement.bind_text16(10, position.address.city.c_str())) {
 
131
    LOG_BIND_ERROR("city");
 
132
    return false;
 
133
  }
 
134
  if (SQLITE_OK != statement.bind_text16(11, position.address.county.c_str())) {
 
135
    LOG_BIND_ERROR("county");
 
136
    return false;
 
137
  }
 
138
  if (SQLITE_OK != statement.bind_text16(12, position.address.region.c_str())) {
 
139
    LOG_BIND_ERROR("region");
 
140
    return false;
 
141
  }
 
142
  if (SQLITE_OK !=
 
143
      statement.bind_text16(13, position.address.country.c_str())) {
 
144
    LOG_BIND_ERROR("country");
 
145
    return false;
 
146
  }
 
147
  if (SQLITE_OK !=
 
148
      statement.bind_text16(14, position.address.country_code.c_str())) {
 
149
    LOG_BIND_ERROR("country code");
 
150
    return false;
 
151
  }
 
152
  if (SQLITE_OK !=
 
153
      statement.bind_text16(15, position.address.postal_code.c_str())) {
 
154
    LOG_BIND_ERROR("postal code");
 
155
    return false;
 
156
  }
 
157
  if (SQLITE_OK != statement.bind_int(16, position.error_code)) {
 
158
    LOG_BIND_ERROR("error code");
 
159
    return false;
 
160
  }
 
161
  if (SQLITE_OK != statement.bind_text16(17, position.error_message.c_str())) {
 
162
    LOG_BIND_ERROR("error message");
 
163
    return false;
 
164
  }
 
165
 
 
166
 
 
167
  if (SQLITE_DONE != statement.step()) {
 
168
    LOG(("PositionTable::SetPosition unable to step: %d.\n",
 
169
         db_->GetErrorCode()));
 
170
    return false;
 
171
  }
 
172
 
 
173
  return transaction.Commit();
 
174
}
 
175
 
 
176
bool PositionTable::GetPosition(const std::string16 &name,
 
177
                                Position *position) {
 
178
  assert(position);
 
179
 
 
180
  const char16 *sql = STRING16(L"SELECT * "
 
181
                               L"FROM " POSITION L" "
 
182
                               L"WHERE " NAME L" = ? ");
 
183
 
 
184
  SQLStatement statement;
 
185
  if (SQLITE_OK != statement.prepare16(db_, sql)) {
 
186
    LOG(("PositionTable::GetPosition unable to prepare: %d.\n",
 
187
         db_->GetErrorCode()));
 
188
    return false;
 
189
  }
 
190
 
 
191
  if (SQLITE_OK != statement.bind_text16(0, name.c_str())) {
 
192
    LOG(("PositionTable::GetPosition unable to bind name: %d.\n",
 
193
         db_->GetErrorCode()));
 
194
    return false;
 
195
  }
 
196
 
 
197
  int rc = statement.step();
 
198
  if (SQLITE_DONE == rc) {
 
199
    return false;
 
200
  } else if (SQLITE_ROW != rc) {
 
201
    LOG(("PositionTable::GetPosition results error: %d.\n",
 
202
         db_->GetErrorCode()));
 
203
    return false;
 
204
  }
 
205
 
 
206
  // Skip Name at index 0.
 
207
  position->latitude              = statement.column_double(1);
 
208
  position->longitude             = statement.column_double(2);
 
209
  // The Altitude, Accuracy and AltitudeAccuracy columns have type INTEGER, but
 
210
  // we can safely store and extract floating point values because SQLite uses
 
211
  // type affinity. See http://www.sqlite.org/datatype3.html#affinity.
 
212
  position->altitude              = statement.column_double(3);
 
213
  position->accuracy              = statement.column_double(4);
 
214
  position->altitude_accuracy     = statement.column_double(5);
 
215
  position->timestamp             = statement.column_int64(6);
 
216
  position->address.street_number = statement.column_text16_safe(7);
 
217
  position->address.street        = statement.column_text16_safe(8);
 
218
  position->address.premises      = statement.column_text16_safe(9);
 
219
  position->address.city          = statement.column_text16_safe(10);
 
220
  position->address.county        = statement.column_text16_safe(11);
 
221
  position->address.region        = statement.column_text16_safe(12);
 
222
  position->address.country       = statement.column_text16_safe(13);
 
223
  position->address.country_code  = statement.column_text16_safe(14);
 
224
  position->address.postal_code   = statement.column_text16_safe(15);
 
225
  int error_code                  = statement.column_int(16);
 
226
  position->error_message         = statement.column_text16_safe(17);
 
227
 
 
228
  switch (error_code) {
 
229
    case Position::ERROR_CODE_POSITION_UNAVAILABLE:
 
230
      position->error_code = Position::ERROR_CODE_POSITION_UNAVAILABLE;
 
231
      break;
 
232
    case Position::ERROR_CODE_TIMEOUT:
 
233
      position->error_code = Position::ERROR_CODE_TIMEOUT;
 
234
      break;
 
235
    default:
 
236
      // Note that in previous versions, error_code was set to kint32min to
 
237
      // signify no error.
 
238
      position->error_code = Position::ERROR_CODE_NONE;
 
239
  }
 
240
 
 
241
  return true;
 
242
}
 
243
 
 
244
bool PositionTable::DeletePosition(const std::string16 &name) {
 
245
  const char16 *sql = STRING16(L"DELETE FROM " POSITION L" "
 
246
                               L"WHERE " NAME L" = ?");
 
247
 
 
248
  SQLStatement statement;
 
249
  if (SQLITE_OK != statement.prepare16(db_, sql)) {
 
250
    LOG(("PositionTable::DeletePosition unable to prepare: %d.\n",
 
251
         db_->GetErrorCode()));
 
252
    return false;
 
253
  }
 
254
 
 
255
  if (SQLITE_OK != statement.bind_text16(0, name.c_str())) {
 
256
    LOG(("PositionTable::DeletePosition unable to bind name: %d.\n",
 
257
         db_->GetErrorCode()));
 
258
    return false;
 
259
  }
 
260
 
 
261
  if (SQLITE_DONE != statement.step()) {
 
262
    LOG(("PositionTable::DeletePosition unable to step: %d.\n",
 
263
         db_->GetErrorCode()));
 
264
    return false;
 
265
  }
 
266
 
 
267
  return true;
 
268
}
 
269
 
 
270
bool PositionTable::CreateVersion1() {
 
271
  SQLTransaction transaction(db_, "PositionTable::CreateVersion1");
 
272
  if (!transaction.Begin()) {
 
273
    return false;
 
274
  }
 
275
 
 
276
  if (SQLITE_OK != db_->Execute(kCreateTableVersion1Statement)) {
 
277
    LOG(("PositionTable::CreateVersion1 unable to execute %d.\n",
 
278
         db_->GetErrorCode()));
 
279
    return false;
 
280
  }
 
281
 
 
282
  return transaction.Commit();
 
283
}