Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: sql/recovery.cc

Issue 1665913003: [sql] Use IGNORE conflict resolution in recovery. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@zzsql_recover_autorecover_review
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sql/recovery.h" 5 #include "sql/recovery.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 // seen. |pk_column_count| counts the columns in the primary key. 368 // seen. |pk_column_count| counts the columns in the primary key.
369 // |rowid_decl| stores the ROWID version of the last INTEGER column 369 // |rowid_decl| stores the ROWID version of the last INTEGER column
370 // seen, which is at |rowid_ofs| in |create_column_decls|. 370 // seen, which is at |rowid_ofs| in |create_column_decls|.
371 size_t pk_column_count = 0; 371 size_t pk_column_count = 0;
372 size_t rowid_ofs = 0; // Only valid if rowid_decl is set. 372 size_t rowid_ofs = 0; // Only valid if rowid_decl is set.
373 std::string rowid_decl; // ROWID version of column |rowid_ofs|. 373 std::string rowid_decl; // ROWID version of column |rowid_ofs|.
374 374
375 while (s.Step()) { 375 while (s.Step()) {
376 const std::string column_name(s.ColumnString(1)); 376 const std::string column_name(s.ColumnString(1));
377 const std::string column_type(s.ColumnString(2)); 377 const std::string column_type(s.ColumnString(2));
378 const bool not_null = s.ColumnBool(3);
379 const int default_type = s.ColumnType(4); 378 const int default_type = s.ColumnType(4);
380 const bool default_is_null = (default_type == COLUMN_TYPE_NULL); 379 const bool default_is_null = (default_type == COLUMN_TYPE_NULL);
381 const int pk_column = s.ColumnInt(5); 380 const int pk_column = s.ColumnInt(5);
382 381
383 // http://www.sqlite.org/pragma.html#pragma_table_info documents column 5 as 382 // http://www.sqlite.org/pragma.html#pragma_table_info documents column 5 as
384 // the 1-based index of the column in the primary key, otherwise 0. 383 // the 1-based index of the column in the primary key, otherwise 0.
385 if (pk_column > 0) 384 if (pk_column > 0)
386 ++pk_column_count; 385 ++pk_column_count;
387 386
388 // Construct column declaration as "name type [optional constraint]". 387 // Construct column declaration as "name type [optional constraint]".
(...skipping 26 matching lines...) Expand all
415 // - contains("CLOB") -> TEXT 414 // - contains("CLOB") -> TEXT
416 // - contains("REAL") -> FLOAT 415 // - contains("REAL") -> FLOAT
417 // - contains("FLOA") -> FLOAT 416 // - contains("FLOA") -> FLOAT
418 // - other -> "NUMERIC" 417 // - other -> "NUMERIC"
419 // Just code those in as they come up. 418 // Just code those in as they come up.
420 NOTREACHED() << " Unsupported type " << column_type; 419 NOTREACHED() << " Unsupported type " << column_type;
421 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVER_UNRECOGNIZED_TYPE); 420 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVER_UNRECOGNIZED_TYPE);
422 return false; 421 return false;
423 } 422 }
424 423
425 // If column has constraint "NOT NULL", then inserting NULL into
426 // that column will fail. If the column has a non-NULL DEFAULT
427 // specified, the INSERT will handle it (see below). If the
428 // DEFAULT is also NULL, the row must be filtered out.
429 // TODO(shess): The above scenario applies to INSERT OR REPLACE,
430 // whereas INSERT OR IGNORE drops such rows.
431 // http://www.sqlite.org/lang_conflict.html
Ryan Hamilton 2016/02/04 01:38:17 Looks like you planned ahead! Nice comment.
432 if (not_null && default_is_null)
433 column_decl += " NOT NULL";
434
435 create_column_decls.push_back(column_decl); 424 create_column_decls.push_back(column_decl);
436 425
437 // Per the NOTE in the header file, convert NULL values to the 426 // Per the NOTE in the header file, convert NULL values to the
438 // DEFAULT. All columns could be IFNULL(column_name,default), but 427 // DEFAULT. All columns could be IFNULL(column_name,default), but
439 // the NULL case would require special handling either way. 428 // the NULL case would require special handling either way.
440 if (default_is_null) { 429 if (default_is_null) {
441 insert_columns.push_back(column_name); 430 insert_columns.push_back(column_name);
442 } else { 431 } else {
443 // The default value appears to be pre-quoted, as if it is 432 // The default value appears to be pre-quoted, as if it is
444 // literally from the sqlite_master CREATE statement. 433 // literally from the sqlite_master CREATE statement.
(...skipping 12 matching lines...) Expand all
457 // If the PRIMARY KEY was a single INTEGER column, convert it to ROWID. 446 // If the PRIMARY KEY was a single INTEGER column, convert it to ROWID.
458 if (pk_column_count == 1 && !rowid_decl.empty()) 447 if (pk_column_count == 1 && !rowid_decl.empty())
459 create_column_decls[rowid_ofs] = rowid_decl; 448 create_column_decls[rowid_ofs] = rowid_decl;
460 449
461 std::string recover_create(base::StringPrintf( 450 std::string recover_create(base::StringPrintf(
462 "CREATE VIRTUAL TABLE temp.recover_%s USING recover(corrupt.%s, %s)", 451 "CREATE VIRTUAL TABLE temp.recover_%s USING recover(corrupt.%s, %s)",
463 table_name, 452 table_name,
464 table_name, 453 table_name,
465 base::JoinString(create_column_decls, ",").c_str())); 454 base::JoinString(create_column_decls, ",").c_str()));
466 455
456 // INSERT OR IGNORE means that it will drop rows resulting from constraint
457 // violations. INSERT OR REPLACE only handles UNIQUE constraint violations.
467 std::string recover_insert(base::StringPrintf( 458 std::string recover_insert(base::StringPrintf(
468 "INSERT OR REPLACE INTO main.%s SELECT %s FROM temp.recover_%s", 459 "INSERT OR IGNORE INTO main.%s SELECT %s FROM temp.recover_%s",
469 table_name, 460 table_name,
470 base::JoinString(insert_columns, ",").c_str(), 461 base::JoinString(insert_columns, ",").c_str(),
471 table_name)); 462 table_name));
472 463
473 std::string recover_drop(base::StringPrintf( 464 std::string recover_drop(base::StringPrintf(
474 "DROP TABLE temp.recover_%s", table_name)); 465 "DROP TABLE temp.recover_%s", table_name));
475 466
476 if (!db()->Execute(recover_create.c_str())) { 467 if (!db()->Execute(recover_create.c_str())) {
477 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVER_CREATE); 468 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVER_CREATE);
478 return false; 469 return false;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 } 519 }
529 return false; 520 return false;
530 } 521 }
531 522
532 RecordRecoveryEvent(RECOVERY_SUCCESS_META_VERSION); 523 RecordRecoveryEvent(RECOVERY_SUCCESS_META_VERSION);
533 *version = recovery_version.ColumnInt(0); 524 *version = recovery_version.ColumnInt(0);
534 return true; 525 return true;
535 } 526 }
536 527
537 } // namespace sql 528 } // namespace sql
OLDNEW
« no previous file with comments | « sql/recovery.h ('k') | sql/recovery_unittest.cc » ('j') | sql/recovery_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698