// File: /workspace/github_c_makefile_star2_O2/barabo[P]advanced-shell-history/src/database.cpp
// Function: ash::Database::exec(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, int) const
ResultSet * Database::exec(const string & query, const int limit) const {
  // Load the relevant configured values.
  Config & config = Config::instance();

  int max_retries = config.get_int("DB_MAX_RETRIES", -1);
  if (max_retries <= 0) max_retries = 5;
  int tries = max_retries + 1, fetched = 0;

  ResultSet::HeadersType headers;
  ResultSet::DataType results;
  stringstream ss;
  sqlite3_stmt * ps = prepare_stmt(query);
  unsigned int rows, columns = sqlite3_column_count(ps);

  // YES, this is a GOTO target.  This is used to implement the retry logic.
  // If a query fails because of a lock, it may goto this block to retry.
try_sql:
  fetched = 0;
  for (rows = 0; fetched < limit || limit <= 0; ++rows) {
    int result = sqlite3_step(ps);
    switch (result) {
      // TODO(cpa): add more cases to handle errors.
      case SQLITE_ROW:
        // build the list of header names, if this is the first row fetched.
        if (headers.empty()) {
          for (size_t c = 0; c < columns; ++c) {
            ss.str("");
            ss << sqlite3_column_name(ps, c);
            headers.push_back(ss.str());
          }
        }
        // Add the row data.
        results.push_back(ResultSet::RowType());
        for (size_t c = 0; c < columns; ++c) {
          ss.str("");
          if (sqlite3_column_text(ps, c)) {
            ss << sqlite3_column_text(ps, c);
          }
          results.back().push_back(ss.str());
        }
        ++fetched;
        continue;  // for loop
      case SQLITE_CONSTRAINT:
        // Note: there is no point retrying this type of error.
        LOG(DEBUG) << "constraint violation executing: '" << query << "'";
        goto finalize;
      case SQLITE_DONE:
        goto finalize;
      case SQLITE_LOCKED:  // Fallthrough.
      case SQLITE_BUSY: {
        // Abort if we are out of attempts.
        if (tries <= 0) {
          LOG(FATAL) << "Failed to unlock db: " << sqlite3_errmsg(db)
                     << "\nGave up after " << max_retries << " failures."
                     << "\nExecuting: '" << query << "'\n";
        }

        // Sleep some random number of milliseconds.
        ash_sleep();

        // Reset the prepared statement.
        sqlite3_finalize(ps);
        ps = prepare_stmt(query);

        // Decrement the try count and jump.
        --tries;
        LOG(WARNING) << "Database was locked, tries remaining: " << tries;
        goto try_sql;
      }
      default:
        sqlite3_finalize(ps);
        // TODO(cpa): remove this cerr line once the FATAL errors are redirected to stderr by default.
        cerr << "unknown sqlite3_step code: " << result << " executing '"
             << query << "'\nError:\n" << sqlite3_errmsg(db) << endl;
        LOG(FATAL) << "unknown sqlite3_step code: " << result
                   << " executing '" << query << "'\nError:\n"
                   << sqlite3_errmsg(db);
    }  // switch
  }  // for loop

  // Yes, another GOTO target.  This is used because there is a switch statement
  // within a for loop and it's convenient to break the loop within the switch.
finalize:
  sqlite3_finalize(ps);

  return rows ? new ResultSet(headers, results) : 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x518, %rsp            # imm = 0x518
movl %edx, 0x2c(%rsp)
movq %rsi, 0x10(%rsp)
movq %rdi, 0x18(%rsp)
callq 0x5d6d2
movq %rax, %rbx
leaq 0x11c30(%rip), %rsi     # 0x6fa9e
leaq 0x70(%rsp), %rdi
leaq 0x390(%rsp), %rdx
callq 0x8150
leaq 0x70(%rsp), %rsi
pushq $-0x1
popq %rdx
movq %rbx, %rdi
callq 0x5d632
movl %eax, %ebx
leaq 0x70(%rsp), %rdi
callq 0x84b0
testl %ebx, %ebx
pushq $0x5
popq %r14
cmovgl %ebx, %r14d
leaq 0x50(%rsp), %rax
movq %rax, 0x8(%rax)
movq %rax, (%rax)
andq $0x0, 0x10(%rax)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
andq $0x0, 0x40(%rsp)
leaq 0x390(%rsp), %rdi
callq 0x8260
movq 0x18(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x5ed30
movq %rax, %r15
movq %rax, %rdi
callq 0xf4e7
movq %r14, 0x68(%rsp)
leal 0x1(%r14), %ecx
movl %ecx, 0xc(%rsp)
movl %eax, %r13d
leaq 0x3a8(%rsp), %r12
leaq 0x70(%rsp), %rbp
movl $0x0, 0x28(%rsp)
movl $0x0, 0x24(%rsp)
movl 0x2c(%rsp), %ecx
testl %ecx, %ecx
setg %al
cmpl %ecx, 0x28(%rsp)
setge %cl
testb %cl, %al
jne 0x5e2c8
movq %r15, %rdi
callq 0xe65d
movl %eax, %ebx
cmpl $0x64, %eax
je 0x5e050
leal -0x5(%rbx), %eax
cmpl $0x2, %eax
jb 0x5e18a
cmpl $0x13, %ebx
je 0x5e285
cmpl $0x65, %ebx
je 0x5e2c8
movq %r15, %rdi
callq 0xdbaa
movq 0x2907f(%rip), %rdi     # 0x86ff0
leaq 0x11ed3(%rip), %rsi     # 0x6fe4b
callq 0x83a0
movq %rax, %rdi
movl %ebx, %esi
callq 0x86a0
movq %rax, %rdi
leaq 0x11ed6(%rip), %rsi     # 0x6fe67
callq 0x83a0
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x8320
movq %rax, %rdi
leaq 0x11ec7(%rip), %rsi     # 0x6fe74
callq 0x83a0
movq %rax, %r14
movq 0x18(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x11788
movq %r14, %rdi
movq %rax, %rsi
callq 0x83a0
movq %rax, %rdi
callq 0x81a0
movq %rbp, %rdi
pushq $0x4
popq %rsi
callq 0x62c92
leaq 0x78(%rsp), %rdi
leaq 0x11e5e(%rip), %rsi     # 0x6fe4b
callq 0x83a0
movq %rax, %rdi
movl %ebx, %esi
callq 0x86a0
movq %rax, %rdi
leaq 0x11e61(%rip), %rsi     # 0x6fe67
callq 0x83a0
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x8320
movq %rax, %rdi
leaq 0x11e52(%rip), %rsi     # 0x6fe74
callq 0x83a0
movq %rax, %rbx
movq 0x18(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x11788
movq %rbx, %rdi
movq %rax, %rsi
callq 0x83a0
movq %rbp, %rdi
callq 0x62fc8
jmp 0x5e110
leaq 0x50(%rsp), %rax
cmpq %rax, 0x50(%rsp)
je 0x5e119
xorps %xmm0, %xmm0
movaps %xmm0, 0x70(%rsp)
andq $0x0, 0x80(%rsp)
leaq 0x30(%rsp), %rdi
movq %rbp, %rsi
callq 0x5f1fe
movq %rbp, %rdi
callq 0x5c66e
xorl %ebx, %ebx
cmpq %rbx, %r13
je 0x5e10c
movq %rbp, %rdi
leaq 0x122ae(%rip), %rsi     # 0x70345
leaq 0xb(%rsp), %rdx
callq 0x8150
movq %r12, %rdi
movq %rbp, %rsi
callq 0x85b0
movq %rbp, %rdi
callq 0x84b0
movq %r15, %rdi
movl %ebx, %esi
callq 0xf68b
testq %rax, %rax
je 0x5e0dd
movq %r15, %rdi
movl %ebx, %esi
callq 0xf68b
leaq 0x3a0(%rsp), %rdi
movq %rax, %rsi
callq 0x83a0
movq 0x38(%rsp), %r14
movq %rbp, %rdi
movq %r12, %rsi
callq 0x8610
addq $-0x18, %r14
movq %r14, %rdi
movq %rbp, %rsi
callq 0x5f22a
movq %rbp, %rdi
callq 0x84b0
incq %rbx
jmp 0x5e088
incl 0x28(%rsp)
incl 0x24(%rsp)
jmp 0x5df19
xorl %ebx, %ebx
cmpq %rbx, %r13
je 0x5e060
movq %rbp, %rdi
leaq 0x12217(%rip), %rsi     # 0x70345
leaq 0xb(%rsp), %rdx
callq 0x8150
movq %r12, %rdi
movq %rbp, %rsi
callq 0x85b0
movq %rbp, %rdi
callq 0x84b0
movq %r15, %rdi
movl %ebx, %esi
callq 0xf73d
leaq 0x3a0(%rsp), %rdi
movq %rax, %rsi
callq 0x83a0
movq %rbp, %rdi
movq %r12, %rsi
callq 0x8610
leaq 0x50(%rsp), %rdi
movq %rbp, %rsi
callq 0x5f1f2
movq %rbp, %rdi
callq 0x84b0
incq %rbx
jmp 0x5e11b
cmpl $0x0, 0xc(%rsp)
jg 0x5e22b
movq %rbp, %rdi
pushq $0x4
popq %rsi
callq 0x62c92
leaq 0x78(%rsp), %rdi
leaq 0x11c41(%rip), %rsi     # 0x6fded
callq 0x83a0
movq %rax, %rbx
movq 0x18(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x11788
movq %rbx, %rdi
movq %rax, %rsi
callq 0x83a0
movq %rax, %rdi
leaq 0x11c2c(%rip), %rsi     # 0x6fe03
callq 0x83a0
movq %rax, %rdi
movq 0x68(%rsp), %rsi
callq 0x86a0
movq %rax, %rdi
leaq 0x11ab9(%rip), %rsi     # 0x6fcac
callq 0x83a0
movq %rax, %rdi
leaq 0x11c11(%rip), %rsi     # 0x6fe13
callq 0x83a0
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x8320
movq %rax, %rdi
leaq 0x11c03(%rip), %rsi     # 0x6fe21
callq 0x83a0
movq %rbp, %rdi
callq 0x62fc8
callq 0x5e65c
movq %r15, %rdi
callq 0xdbaa
movq 0x18(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x5ed30
movq %rax, %r15
movq %rbp, %rdi
pushq $0x2
popq %rsi
callq 0x62c92
leaq 0x78(%rsp), %rdi
leaq 0x11bc3(%rip), %rsi     # 0x6fe24
callq 0x83a0
movl 0xc(%rsp), %esi
decl %esi
movq %rax, %rdi
movl %esi, 0xc(%rsp)
callq 0x86a0
movq %rbp, %rdi
callq 0x62fc8
jmp 0x5df09
leaq 0x70(%rsp), %rdi
xorl %esi, %esi
callq 0x62c92
leaq 0x78(%rsp), %rdi
leaq 0x11b2e(%rip), %rsi     # 0x6fdcb
callq 0x83a0
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x8320
leaq 0x12059(%rip), %rsi     # 0x7030f
movq %rax, %rdi
callq 0x83a0
leaq 0x70(%rsp), %rdi
callq 0x62fc8
movq %r15, %rdi
callq 0xdbaa
cmpl $0x0, 0x24(%rsp)
je 0x5e2f6
pushq $0x40
popq %rdi
callq 0x83c0
movq %rax, %r14
leaq 0x50(%rsp), %rsi
leaq 0x30(%rsp), %rdx
movq %rax, %rdi
callq 0x5d930
jmp 0x5e2f9
xorl %r14d, %r14d
leaq 0x390(%rsp), %rdi
callq 0x87e8
leaq 0x30(%rsp), %rdi
callq 0x5c5fc
leaq 0x50(%rsp), %rdi
callq 0x5c6e0
movq %r14, %rax
addq $0x518, %rsp            # imm = 0x518
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x5e421
jmp 0x5e421
movq %rax, %rbx
movq %r14, %rdi
callq 0x8370
jmp 0x5e424
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x62fc8
jmp 0x5e424
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x62fc8
jmp 0x5e424
movq %rax, %rbx
jmp 0x5e43b
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x84b0
jmp 0x5e445
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x62fc8
jmp 0x5e424
movq %rax, %rbx
jmp 0x5e431
movq %rax, %rbx
jmp 0x5e445
jmp 0x5e421
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x5c66e
jmp 0x5e424
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x62fc8
jmp 0x5e424
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x84b0
jmp 0x5e424
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x84b0
jmp 0x5e424
jmp 0x5e421
jmp 0x5e421
jmp 0x5e421
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x84b0
jmp 0x5e424
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x84b0
jmp 0x5e424
jmp 0x5e421
jmp 0x5e421
movq %rax, %rbx
leaq 0x390(%rsp), %rdi
callq 0x87e8
leaq 0x30(%rsp), %rdi
callq 0x5c5fc
leaq 0x50(%rsp), %rdi
callq 0x5c6e0
movq %rbx, %rdi
callq 0x86f0
movq %rax, %rdi
callq 0x5c505
nop