void SQLiteStatementImpl::compileImpl()
{
	if (!_pLeftover)
	{
		_bindBegin = bindings().begin();
	}

	std::string statement(toString());

	sqlite3_stmt* pStmt = 0;
	const char* pSql = _pLeftover ? _pLeftover->c_str() : statement.c_str();

	if (0 == std::strlen(pSql))
		throw InvalidSQLStatementException("Empty statements are illegal");

	int rc = SQLITE_OK;
	const char* pLeftover = 0;
	bool queryFound = false;

	do
	{
		rc = sqlite3_prepare_v2(_pDB, pSql, -1, &pStmt, &pLeftover);
		if (rc != SQLITE_OK)
		{
			if (pStmt) sqlite3_finalize(pStmt);
			pStmt = 0;
			std::string errMsg = sqlite3_errmsg(_pDB);
			Utility::throwException(_pDB, rc, errMsg);
		}
		else if (rc == SQLITE_OK && pStmt)
		{
			queryFound = true;
		}
		else if (rc == SQLITE_OK && !pStmt) // comment/whitespace ignore
		{
			pSql = pLeftover;
			if (std::strlen(pSql) == 0)
			{
				// empty statement or an conditional statement! like CREATE IF NOT EXISTS
				// this is valid
				queryFound = true;
			}
		}
	} while (rc == SQLITE_OK && !pStmt && !queryFound);

	//Finalization call in clear() invalidates the pointer, so the value is remembered here.
	//For last statement in a batch (or a single statement), pLeftover == "", so the next call
	// to compileImpl() shall return false immediately when there are no more statements left.
	std::string leftOver(pLeftover);
	trimInPlace(leftOver);
	clear();
	_pStmt = pStmt;
	if (!leftOver.empty())
	{
		_pLeftover = new std::string(leftOver);
		_canCompile = true;
	}
	else _canCompile = false;

	_pBinder = new Binder(_pStmt);
	_pExtractor = new Extractor(_pStmt);

	if (SQLITE_DONE == _nextResponse && _isExtracted)
	{
		//if this is not the first compile and there has already been extraction
		//during previous step, switch to the next set if there is one provided
		if (hasMoreDataSets())
		{
			activateNextDataSet();
			_isExtracted = false;
		}
	}

	int colCount = sqlite3_column_count(_pStmt);

	if (colCount)
	{
		std::size_t curDataSet = currentDataSet();
		if (curDataSet >= _columns.size()) _columns.resize(curDataSet + 1);
		for (int i = 0; i < colCount; ++i)
		{
			MetaColumn mc(i, sqlite3_column_name(_pStmt, i), Utility::getColumnType(_pStmt, i));
				_columns[curDataSet].push_back(mc);
		}
	}
}
dgInt32 dgPolygonSoupDatabaseBuilder::AddConvexFace(dgInt32 count,
    dgInt32* const pool, dgInt32* const facesArray)
{
  dgPolySoupFilterAllocator polyhedra(m_allocator);

  count = polyhedra.AddFilterFace(dgUnsigned32(count), pool);

  dgEdge* edge = &polyhedra.GetRoot()->GetInfo();
  if (edge->m_incidentFace < 0)
  {
    edge = edge->m_twin;
  }

  dgInt32 isconvex = 1;
  dgInt32 facesCount = 0;

  dgInt32 flag = 1;
  while (flag)
  {
    flag = 0;
    if (count >= 3)
    {
      dgEdge* ptr = edge;

      dgBigVector p0(&m_vertexPoints[ptr->m_incidentVertex].m_x);
      do
      {
        dgBigVector p1(&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
        dgBigVector e0(p1 - p0);
        dgFloat64 mag2 = e0 % e0;
        if (mag2 < dgFloat32(1.0e-6f))
        {
          count--;
          flag = 1;
          edge = ptr->m_next;
          ptr->m_prev->m_next = ptr->m_next;
          ptr->m_next->m_prev = ptr->m_prev;
          ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
          ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
          break;
        }
        p0 = p1;
        ptr = ptr->m_next;
      } while (ptr != edge);
    }
  }
  if (count >= 3)
  {
    flag = 1;

    while (flag)
    {
      flag = 0;
      if (count >= 3)
      {
        dgEdge* ptr = edge;

        dgBigVector p0(&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x);
        dgBigVector p1(&m_vertexPoints[ptr->m_incidentVertex].m_x);
        dgBigVector e0(p1 - p0);
        e0 = e0.Scale(dgRsqrt (e0 % e0 + dgFloat32(1.0e-10f)));
        do
        {
          dgBigVector p2(&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
          dgBigVector e1(p2 - p1);

          e1 = e1.Scale(dgRsqrt (e1 % e1 + dgFloat32(1.0e-10f)));
          dgFloat64 mag2 = e1 % e0;
          if (mag2 > dgFloat32(0.9999f))
          {
            count--;
            flag = 1;
            edge = ptr->m_next;
            ptr->m_prev->m_next = ptr->m_next;
            ptr->m_next->m_prev = ptr->m_prev;
            ptr->m_twin->m_next->m_prev = ptr->m_twin->m_prev;
            ptr->m_twin->m_prev->m_next = ptr->m_twin->m_next;
            break;
          }

          e0 = e1;
          p1 = p2;
          ptr = ptr->m_next;
        } while (ptr != edge);
      }
    }

    dgBigVector normal(
        polyhedra.FaceNormal(edge, &m_vertexPoints[0].m_x,
            sizeof(dgBigVector)));
    dgFloat64 mag2 = normal % normal;
    if (mag2 < dgFloat32(1.0e-8f))
    {
      return 0;
    }
    normal = normal.Scale(dgRsqrt (mag2));

    if (count >= 3)
    {
      dgEdge* ptr = edge;
      dgBigVector p0(&m_vertexPoints[ptr->m_prev->m_incidentVertex].m_x);
      dgBigVector p1(&m_vertexPoints[ptr->m_incidentVertex].m_x);
      dgBigVector e0(p1 - p0);
      e0 = e0.Scale(dgRsqrt (e0 % e0 + dgFloat32(1.0e-10f)));
      do
      {
        dgBigVector p2(&m_vertexPoints[ptr->m_next->m_incidentVertex].m_x);
        dgBigVector e1(p2 - p1);

        e1 = e1.Scale(dgRsqrt (e1 % e1 + dgFloat32(1.0e-10f)));

        dgBigVector n(e0 * e1);
        dgFloat64 mag2 = n % normal;
        if (mag2 < dgFloat32(1.0e-5f))
        {
          isconvex = 0;
          break;
        }

        e0 = e1;
        p1 = p2;
        ptr = ptr->m_next;
      } while (ptr != edge);
    }
  }

  if (isconvex)
  {
    dgEdge* const first = edge;
    if (count >= 3)
    {
      count = 0;
      dgEdge* ptr = first;
      do
      {
        pool[count] = ptr->m_incidentVertex;
        count++;
        ptr = ptr->m_next;
      } while (ptr != first);
      facesArray[facesCount] = count;
      facesCount = 1;
    }
  }
  else
  {
    dgPolyhedra leftOver(m_allocator);
    dgPolyhedra polyhedra2(m_allocator);
    dgEdge* ptr = edge;
    count = 0;
    do
    {
      pool[count] = ptr->m_incidentVertex;
      count++;
      ptr = ptr->m_next;
    } while (ptr != edge);

    polyhedra2.BeginFace();
    polyhedra2.AddFace(count, pool);
    polyhedra2.EndFace();
    leftOver.BeginFace();
    polyhedra2.ConvexPartition(&m_vertexPoints[0].m_x, sizeof(dgTriplex),
        &leftOver);
    leftOver.EndFace();
    _ASSERTE(leftOver.GetCount() == 0);

    dgInt32 mark = polyhedra2.IncLRU();
    dgInt32 index = 0;
    dgPolyhedra::Iterator iter(polyhedra2);
    for (iter.Begin(); iter; iter++)
    {
      dgEdge* const edge = &(*iter);
      if (edge->m_incidentFace < 0)
      {
        continue;
      }
      if (edge->m_mark == mark)
      {
        continue;
      }

      ptr = edge;
      count = 0;
      do
      {
        ptr->m_mark = mark;
        pool[index] = ptr->m_incidentVertex;
        index++;
        count++;
        ptr = ptr->m_next;
      } while (ptr != edge);

      facesArray[facesCount] = count;
      facesCount++;
    }
  }

  return facesCount;
}