/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2022 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "ndn-cxx/util/sqlite3-statement.hpp"

#include <sqlite3.h>

namespace ndn {
namespace util {

Sqlite3Statement::~Sqlite3Statement()
{
  sqlite3_finalize(m_stmt);
}

Sqlite3Statement::Sqlite3Statement(sqlite3* database, const std::string& statement)
{
  int res = sqlite3_prepare_v2(database, statement.data(), -1, &m_stmt, nullptr);
  if (res != SQLITE_OK)
    NDN_THROW(std::domain_error("bad SQL statement: " + statement));
}

int
Sqlite3Statement::bind(int index, const char* value, size_t size, void(*destructor)(void*))
{
  return sqlite3_bind_text(m_stmt, index, value, size, destructor);
}

int
Sqlite3Statement::bind(int index, const std::string& value, void(*destructor)(void*))
{
  return sqlite3_bind_text(m_stmt, index, value.data(), value.size(), destructor);
}

int
Sqlite3Statement::bind(int index, const void* buf, size_t size, void(*destructor)(void*))
{
  return sqlite3_bind_blob(m_stmt, index, buf, size, destructor);
}

int
Sqlite3Statement::bind(int index, const Block& block, void(*destructor)(void*))
{
  return sqlite3_bind_blob(m_stmt, index, block.data(), block.size(), destructor);
}

int
Sqlite3Statement::bind(int index, int number)
{
  return sqlite3_bind_int(m_stmt, index, number);
}

std::string
Sqlite3Statement::getString(int column)
{
  return std::string(reinterpret_cast<const char*>(sqlite3_column_text(m_stmt, column)),
                     sqlite3_column_bytes(m_stmt, column));
}

Block
Sqlite3Statement::getBlock(int column)
{
  return Block(make_span(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(m_stmt, column)),
                         sqlite3_column_bytes(m_stmt, column)));
}

int
Sqlite3Statement::getInt(int column)
{
  return sqlite3_column_int(m_stmt, column);
}

const uint8_t*
Sqlite3Statement::getBlob(int column)
{
  return static_cast<const uint8_t*>(sqlite3_column_blob(m_stmt, column));
}

int
Sqlite3Statement::getSize(int column)
{
  return sqlite3_column_bytes(m_stmt, column);
}

int
Sqlite3Statement::step()
{
  return sqlite3_step(m_stmt);
}

Sqlite3Statement::operator sqlite3_stmt*()
{
  return m_stmt;
}

} // namespace util
} // namespace ndn
