Пример #1
0
/**
 * @brief Creates simple tile group for testing purposes.
 * @param backend Backend for tile group to use.
 * @param tuple_count Tuple capacity of this tile group.
 *
 * Tile group has two tiles, and each of them has two columns.
 * The first two columns have INTEGER types, the last two have TINYINT
 * and VARCHAR.
 *
 * IMPORTANT: If you modify this function, it is your responsibility to
 *            fix any affected test cases. Test cases may be depending
 *            on things like the specific number of tiles in this group.
 *
 * @return Pointer to tile group.
 */
storage::TileGroup *ExecutorTestsUtil::CreateTileGroup(int tuple_count) {
  std::vector<catalog::Column> columns;
  std::vector<catalog::Schema> schemas;

  columns.push_back(GetColumnInfo(0));
  columns.push_back(GetColumnInfo(1));
  catalog::Schema schema1(columns);
  schemas.push_back(schema1);

  columns.clear();
  columns.push_back(GetColumnInfo(2));
  columns.push_back(GetColumnInfo(3));

  catalog::Schema schema2(columns);
  schemas.push_back(schema2);

  std::map<oid_t, std::pair<oid_t, oid_t>> column_map;
  column_map[0] = std::make_pair(0, 0);
  column_map[1] = std::make_pair(0, 1);
  column_map[2] = std::make_pair(1, 0);
  column_map[3] = std::make_pair(1, 1);

  storage::TileGroup *tile_group = storage::TileGroupFactory::GetTileGroup(
      INVALID_OID, INVALID_OID,
      TestingHarness::GetInstance().GetNextTileGroupId(), nullptr, schemas,
      column_map, tuple_count);

  return tile_group;
}
Пример #2
0
storage::DataTable *ExecutorTestsUtil::CreateTable(
    int tuples_per_tilegroup_count, bool indexes) {
  catalog::Schema *table_schema = new catalog::Schema(
      {GetColumnInfo(0), GetColumnInfo(1), GetColumnInfo(2), GetColumnInfo(3)});
  std::string table_name("TEST_TABLE");

  // Create table.
  bool own_schema = true;
  bool adapt_table = false;
  storage::DataTable *table = storage::TableFactory::GetDataTable(
      INVALID_OID, INVALID_OID, table_schema, table_name,
      tuples_per_tilegroup_count, own_schema, adapt_table);

  if (indexes == true) {
    // PRIMARY INDEX
    std::vector<oid_t> key_attrs;

    auto tuple_schema = table->GetSchema();
    catalog::Schema *key_schema;
    index::IndexMetadata *index_metadata;
    bool unique;

    key_attrs = {0};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = true;

    index_metadata = new index::IndexMetadata(
        "primary_btree_index", 123, INDEX_TYPE_BTREE,
        INDEX_CONSTRAINT_TYPE_PRIMARY_KEY, tuple_schema, key_schema, unique);

    index::Index *pkey_index = index::IndexFactory::GetInstance(index_metadata);

    table->AddIndex(pkey_index);

    // SECONDARY INDEX
    key_attrs = {0, 1};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = false;
    index_metadata = new index::IndexMetadata(
        "secondary_btree_index", 124, INDEX_TYPE_BTREE,
        INDEX_CONSTRAINT_TYPE_DEFAULT, tuple_schema, key_schema, unique);
    index::Index *sec_index = index::IndexFactory::GetInstance(index_metadata);

    table->AddIndex(sec_index);
  }

  return table;
}
Пример #3
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pWnd - 
//-----------------------------------------------------------------------------
void CMySplitterWnd::ToggleMax(CWnd *pWnd)
{
	int ir, ic;

	if(!pMaxPrev)
	{
		int dummy;
		// save current info
		GetRowInfo(0, sizePrev[1][0], dummy);
		GetRowInfo(1, sizePrev[1][1], dummy);
		GetColumnInfo(0, sizePrev[0][0], dummy);
		GetColumnInfo(1, sizePrev[0][1], dummy);
	}

	if(pWnd != pMaxPrev)
	{
		// maximize this one
		int iRow, iCol;
		CRect r;
		GetClientRect(r);
		VERIFY(IsChildPane(pWnd, &iRow, &iCol));

		for(ir = 0; ir < 2; ir++)
		{
			for(ic = 0; ic < 2; ic++)
			{
				SetRowInfo(ir, 0, 0);
				SetColumnInfo(ic, 0, 0);
			}
		}

		SetRowInfo(iRow, r.Height(), 5);
		SetColumnInfo(iCol, r.Width(), 5);

		pMaxPrev = pWnd;
	}
	else
	{
		// restore saved info
		SetRowInfo(0, sizePrev[1][0], 0);
		SetRowInfo(1, sizePrev[1][1], 0);
		SetColumnInfo(0, sizePrev[0][0], 0);
		SetColumnInfo(1, sizePrev[0][1], 0);

		pMaxPrev = NULL;
	}

	RecalcLayout();
}
Пример #4
0
// IColumnProvider members
STDMETHODIMP CShellExt::GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci)
{
	PreserveChdir preserveChdir;
	if (dwIndex > 0) // TODO: keep for now to be able to hide unimplemented columns
		return S_FALSE;

	ShellCache::CacheType cachetype = g_ShellCache.GetCacheType();
	if (cachetype == ShellCache::none)
		return S_FALSE;

	LoadLangDll();
	switch (dwIndex)
	{
		case 0:	// Git Status
			GetColumnInfo(dwIndex, psci, 15, IDS_COLTITLESTATUS, IDS_COLDESCSTATUS);
			break;
		case 1:	// Git Revision
			GetColumnInfo(dwIndex, psci, 40, IDS_COLTITLEREV, IDS_COLDESCREV);
			break;
		case 2:	// Git Url
			GetColumnInfo(dwIndex, psci, 30, IDS_COLTITLEURL, IDS_COLDESCURL);
			break;
		case 3:	// Git Short Url
			GetColumnInfo(dwIndex, psci, 30, IDS_COLTITLESHORTURL, IDS_COLDESCSHORTURL);
			break;
		case 4:	// Author and Git Author
			psci->scid.fmtid = FMTID_SummaryInformation;	// predefined FMTID
			psci->scid.pid   = PIDSI_AUTHOR;				// Predefined - author
			psci->vt         = VT_LPSTR;					// We'll return the data as a string
			psci->fmt        = LVCFMT_LEFT;					// Text will be left-aligned in the column
			psci->csFlags    = SHCOLSTATE_TYPE_STR;			// Data should be sorted as strings
			psci->cChars     = 32;							// Default col width in chars
			MAKESTRING(IDS_COLTITLEAUTHOR);
			lstrcpynW(psci->wszTitle, stringtablebuffer, MAX_COLUMN_NAME_LEN);
			MAKESTRING(IDS_COLDESCAUTHOR);
			lstrcpynW(psci->wszDescription, stringtablebuffer, MAX_COLUMN_DESC_LEN);
			break;
		case 5:	// SVN eol-style
			GetColumnInfo(dwIndex, psci, 30, IDS_COLTITLEEOLSTYLE, IDS_COLDESCEOLSTYLE);
			break;
		default:
			return S_FALSE;
	}

	return S_OK;
}
Пример #5
0
ValueMap Sql::GetRowMap() const
{
	ValueMap m;
	int n = GetColumns();
	for(int i = 0; i < n; i++)
		m.Add(GetColumnInfo(i).name, (*this)[i]);
	return m;
}
Пример #6
0
void CTabSplitterWnd::SaveSize()
{
#ifdef _DEBUG
	if (m_strSection == szSplitterSection)
		TRACE0("Warning: SetSection has not been called in IMSplitterWnd!\n");
#endif

	GetColumnInfo(0, m_cxCur, m_cxMin);

	if (m_cxCur)
		afxGetApp()->WriteProfileInt(m_strSection, szPaneWidthCurrent, m_cxCur);

	if (m_cxMin)
		afxGetApp()->WriteProfileInt(m_strSection, szPaneWidthMinimum, m_cxMin);

	GetRowInfo(0, m_cyCur, m_cyMin);

	if (m_cyCur)
		afxGetApp()->WriteProfileInt(m_strSection, szPaneHeightCurrent, m_cyCur);
	
	if (m_cyMin)
		afxGetApp()->WriteProfileInt(m_strSection, szPaneHeightMinimum, m_cyMin);
}
TableProperties::TableProperties(BString tableName) 
: fTableName(tableName),
  fColumns()
{
	GetColumnInfo();
	GetIndexList();
	
	//The column types returned by SQLite could be anything; since it's typeless,
	//it places no restriction on what the column types are.  Thus, we'll try to
	//convert the column types returned by SQLite into one of the predefined types
	//used by BeAccessible (which currently are AutoNumber, Number, DateTime, Boolean,
	//and Text.
	ConvertDataTypes();

	//Create a mapping between column names and their column properties structure
	for(int i = 0; i < fColumns.CountItems(); i++)
	{
		ColumnProperties* col = static_cast<ColumnProperties*>(fColumns.ItemAt(i));
		fColumnMapping.fMapping[col->Name()] = col;
	}

	//Get the table_preferences XML for the given table
	GetTableXML();
}
Пример #8
0
void LogicalTile::MaterializeColumnAtATime(
    const std::unordered_map<oid_t, oid_t> &old_to_new_cols,
    const std::unordered_map<storage::Tile *, std::vector<oid_t>> &tile_to_cols,
    storage::Tile *dest_tile) {
  ///////////////////////////
  // EACH PHYSICAL TILE
  ///////////////////////////
  // Copy over all data from each base tile.
  for (const auto &kv : tile_to_cols) {
    const std::vector<oid_t> &old_column_ids = kv.second;

    ///////////////////////////
    // EACH COLUMN
    ///////////////////////////
    // Go over each column in given base physical tile
    for (oid_t old_col_id : old_column_ids) {
      auto &column_info = GetColumnInfo(old_col_id);

      // Amortize schema lookups once per column
      storage::Tile *old_tile = column_info.base_tile.get();
      auto old_schema = old_tile->GetSchema();

      // Get old column information
      oid_t old_column_id = column_info.origin_column_id;
      const size_t old_column_offset = old_schema->GetOffset(old_column_id);
      const ValueType old_column_type = old_schema->GetType(old_column_id);
      const bool old_is_inlined = old_schema->IsInlined(old_column_id);

      // Old to new column mapping
      auto it = old_to_new_cols.find(old_col_id);
      assert(it != old_to_new_cols.end());

      // Get new column information
      oid_t new_column_id = it->second;
      auto new_schema = dest_tile->GetSchema();
      const size_t new_column_offset = new_schema->GetOffset(new_column_id);
      const bool new_is_inlined = new_schema->IsInlined(new_column_id);
      const size_t new_column_length =
          new_schema->GetAppropriateLength(new_column_id);

      // Get the position list
      auto &column_position_list =
          GetPositionList(column_info.position_list_idx);
      oid_t new_tuple_id = 0;

      // Copy all values in the column to the physical tile
      // This uses fast getter and setter functions
      ///////////////////////////
      // EACH TUPLE
      ///////////////////////////
      for (oid_t old_tuple_id : *this) {
        oid_t base_tuple_id = column_position_list[old_tuple_id];
        auto value = old_tile->GetValueFast(base_tuple_id, old_column_offset,
                                            old_column_type, old_is_inlined);

        LOG_TRACE("Old Tuple : %u Column : %u ", old_tuple_id, old_col_id);
        LOG_TRACE("New Tuple : %u Column : %u ", new_tuple_id, new_column_id);

        dest_tile->SetValueFast(value, new_tuple_id, new_column_offset,
                                new_is_inlined, new_column_length);

        // Go to next tuple
        new_tuple_id++;
      }
    }
  }
}
storage::DataTable *ConstraintsTestsUtil::CreateTable(
    int tuples_per_tilegroup_count, bool indexes) {
  catalog::Schema *table_schema = new catalog::Schema(
      {GetColumnInfo(0), GetColumnInfo(1), GetColumnInfo(2), GetColumnInfo(3)});
  std::string table_name("TEST_TABLE");

  // Create table.
  bool own_schema = true;
  bool adapt_table = false;
  storage::DataTable *table = storage::TableFactory::GetDataTable(
      INVALID_OID, INVALID_OID, table_schema, table_name,
      tuples_per_tilegroup_count, own_schema, adapt_table);

  if (indexes == true) {
    // PRIMARY INDEX
    std::vector<oid_t> key_attrs;

    auto tuple_schema = table->GetSchema();
    catalog::Schema *key_schema;
    index::IndexMetadata *index_metadata;
    bool unique;

    key_attrs = {0};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = true;

    index_metadata = new index::IndexMetadata(
        "primary_btree_index", 123, table->GetOid(), table->GetDatabaseOid(),
        IndexType::BWTREE, IndexConstraintType::PRIMARY_KEY, tuple_schema,
        key_schema, key_attrs, unique);

    std::shared_ptr<index::Index> pkey_index(
        index::IndexFactory::GetIndex(index_metadata));

    table->AddIndex(pkey_index);

    // SECONDARY INDEX
    key_attrs = {0, 1};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = false;
    index_metadata = new index::IndexMetadata(
        "secondary_btree_index", 124, table->GetOid(), table->GetDatabaseOid(),
        IndexType::BWTREE, IndexConstraintType::DEFAULT, tuple_schema,
        key_schema, key_attrs, unique);
    std::shared_ptr<index::Index> sec_index(
        index::IndexFactory::GetIndex(index_metadata));

    table->AddIndex(sec_index);

    // SECONDARY INDEX - UNIQUE INDEX
    key_attrs = {3};
    key_schema = catalog::Schema::CopySchema(tuple_schema, key_attrs);
    key_schema->SetIndexedColumns(key_attrs);

    unique = false;
    index_metadata = new index::IndexMetadata(
        "unique_btree_index", 125, table->GetOid(), table->GetDatabaseOid(),
        IndexType::BWTREE, IndexConstraintType::UNIQUE, tuple_schema,
        key_schema, key_attrs, unique);
    std::shared_ptr<index::Index> unique_index(
        index::IndexFactory::GetIndex(index_metadata));

    table->AddIndex(unique_index);
  }

  return table;
}
Пример #10
0
STDMETHODIMP CCUBRIDRowset::Update(HCHAPTER hReserved, DBCOUNTITEM cRows, const HROW rghRows[],
				DBCOUNTITEM *pcRows, HROW **prgRows, DBROWSTATUS **prgRowStatus)
{
	ATLTRACE(atlTraceDBProvider, 2, "CCUBRIDRowset::Update\n");

	ClearError();
	if(m_nStatus==1) return RaiseError(E_UNEXPECTED, 1, __uuidof(IRowsetUpdate), L"This object is in a zombie state");
	CHECK_RESTART(__uuidof(IRowsetUpdate));

	DBCOUNTITEM ulRows = 0; // update할 row 수
	bool bNotIgnore = true; // prgRows, prgRowStatus를 무시할지 여부를 나타냄

	// the following lines are used to fix the two _alloca calls below.  Those calls are risky 
	// because we may be allocating huge amounts of data.  So instead I'll allocate that data on heap.
	// But if you use _alloca you don't have to worry about cleaning this memory.  So we will use these
	// temporary variables to allocate memory on heap.  As soon as we exit the function, the memory will
	// be cleaned up, just as if we were using alloca. So now, instead of calling alloca, I'll alloc
	// memory on heap using the two smnart pointers below, and then assing it to the actual pointers.
	CHeapPtr<HROW> spTempRows;
	CHeapPtr<DBROWSTATUS> spTempRowStatus;

	if(cRows || pcRows)
	{
		if(prgRows) *prgRows = NULL;
		if(prgRowStatus) *prgRowStatus = NULL;		
	}
	else
	{
		bNotIgnore = false;		// Don't do status or row arrays
	}

	// Check to see how many changes we'll undo 
	if(pcRows)
	{
		*pcRows = NULL;
		if(prgRows==NULL) return E_INVALIDARG;
	}

	if(cRows)
	{
		if(rghRows==NULL) return E_INVALIDARG;
		ulRows = cRows;
	}
	else
		ulRows = (DBCOUNTITEM)m_rgRowHandles.GetCount();

	int hConn = GetSessionPtr()->GetConnection();
	UINT uCodepage = GetSessionPtr()->GetCodepage();
	// NULL out pointers
	{
		if(prgRows && ulRows && bNotIgnore)
		{
			// Make a temporary buffer as we may not fill up everything
			// in the case where cRows == 0
			if(cRows)
				*prgRows = (HROW*)CoTaskMemAlloc(ulRows * sizeof(HROW));
			else
			{
				spTempRows.Allocate(ulRows);
				*prgRows = spTempRows;
			}
			if (*prgRows==NULL) return E_OUTOFMEMORY;
		}

		if(prgRowStatus && ulRows && bNotIgnore)
		{
			if(cRows)
				*prgRowStatus = (DBROWSTATUS*)CoTaskMemAlloc(ulRows * sizeof(DBROWSTATUS));
			else
			{
				spTempRowStatus.Allocate(ulRows);
				*prgRowStatus = spTempRowStatus;
			}
			if(*prgRowStatus==NULL)
			{
				if(cRows) CoTaskMemFree(*prgRows);
				*prgRows = NULL;
				return E_OUTOFMEMORY;
			}
		}
	}

	bool bSucceeded = false;
	bool bFailed = false;
	ULONG ulCount = 0; // update된 row 수
	POSITION pos = m_rgRowHandles.GetStartPosition();
	for (ULONG ulRow = 0; ulRow < ulRows; ulRow++)
	{
		ULONG ulCurrentRow = ulCount;
		bool bDupRow = false; // 중복된 row
		ULONG ulAlreadyProcessed = 0; // 중복된 row의 handle의 위치

		HROW hRowUpdate = NULL; // 현재 update할 row의 handle
		{
			if(cRows)
			{	// row handle이 주어졌음
				hRowUpdate = rghRows[ulRow];
				for (ULONG ulCheckDup = 0; ulCheckDup < ulRow; ulCheckDup++)
				{
					if (hRowUpdate==rghRows[ulCheckDup] ||
						IsSameRow(hRowUpdate, rghRows[ulCheckDup]) == S_OK)
					{
						ulAlreadyProcessed = ulCheckDup;
						bDupRow = true;
						break;
					}
				}
			}
			else
			{	// 모든 row에 대해 update
				//ATLASSERT(ulRow < (ULONG)m_rgRowHandles.GetCount()); // delete된 row가 있으면 성립하지 않는다.
				ATLASSERT( pos != NULL );
				MapClass::CPair* pPair = m_rgRowHandles.GetNext(pos);
				ATLASSERT( pPair != NULL );
				hRowUpdate = pPair->m_key;
			}
		}

		if(prgRows && bNotIgnore)
			(*prgRows)[ulCurrentRow] = hRowUpdate;

		if(bDupRow)
		{
			// We've already set the row before, just copy status and
			// continue processing
			if(prgRowStatus && bNotIgnore)
				(*prgRowStatus)[ulCurrentRow] = (*prgRowStatus)[ulAlreadyProcessed];
			ulCount++;
			continue;
		}

		// Fetch the RowClass and determine if it is valid
		CCUBRIDRowsetRow *pRow;
		{
			bool bFound = m_rgRowHandles.Lookup((ULONG)hRowUpdate, pRow);
			if (!bFound || pRow == NULL)
			{
				if (prgRowStatus && bNotIgnore)
					(*prgRowStatus)[ulCurrentRow] = DBROWSTATUS_E_INVALID;
				bFailed = true;
				ulCount++;
				continue;
			}
		}

		// If cRows is zero we'll go through all rows fetched.  We
		// shouldn't increment the attempted count for rows that are
		// not changed
		if (cRows != 0 || (pRow != NULL &&
			pRow->m_status != 0 && pRow->m_status != DBPENDINGSTATUS_UNCHANGED
			&& pRow->m_status != DBPENDINGSTATUS_INVALIDROW))
			ulCount++;
		else
			continue;

		if(cRows==0)
			pRow->AddRefRow();

		switch (pRow->m_status)
		{
		case DBPENDINGSTATUS_INVALIDROW:	// Row is bad or deleted
			{
				if(prgRowStatus && bNotIgnore)
					(*prgRowStatus)[ulCurrentRow] = DBROWSTATUS_E_DELETED;
				bFailed = true;
			}
			break;
		case DBPENDINGSTATUS_UNCHANGED:
		case 0:
			{
				// If the row's status is not changed, then just put S_OK
				// and continue.  The spec says we should not transmit the
				// request to the data source (as nothing would change).
				if(prgRowStatus && bNotIgnore)
					(*prgRowStatus)[ulCurrentRow] = DBROWSTATUS_S_OK;
				bSucceeded = true;
			}
			break;
		default:
			{
				DBORDINAL cCols;
				ATLCOLUMNINFO *pColInfo = GetColumnInfo(this, &cCols);
				HRESULT hr = pRow->WriteData(hConn, uCodepage, GetRequestHandle(), m_strTableName);
				if(FAILED(hr))
				{
					DBROWSTATUS stat = DBROWSTATUS_E_FAIL;
					if(hr==DB_E_INTEGRITYVIOLATION) stat = DBROWSTATUS_E_INTEGRITYVIOLATION;
					if(prgRowStatus && bNotIgnore)
						(*prgRowStatus)[ulCurrentRow] = stat;
					bFailed = true;
				}
				else
				{
					//// m_iRowset을 적당히 조정한다.
					//if(pRow->m_status==DBPENDINGSTATUS_NEW)
					//{
					//	// NEW인 row는 항상 rowset의 뒤에 몰려있다.
					//	// 그 row 중 가장 작은 m_iRowset이 update 된 row의 m_iRowset이 되면 된다.
					//	CCUBRIDRowsetRow::KeyType key = pRow->m_iRowset;
					//	POSITION pos = m_rgRowHandles.GetStartPosition();
					//	while(pos)
					//	{
					//		CCUBRIDRowset::MapClass::CPair *pPair = m_rgRowHandles.GetNext(pos);
					//		ATLASSERT(pPair);
					//		CCUBRIDRowsetRow *pCheckRow = pPair->m_value;
					//		if( pCheckRow && pCheckRow->m_iRowset < key )
					//		{
					//			if(pCheckRow->m_iRowset<pRow->m_iRowset)
					//				pRow->m_iRowset = pCheckRow->m_iRowset;
					//			pCheckRow->m_iRowset++;
					//		}
					//	}

					//	// TODO: 북마크 업데이트가 필요한데 어떻게 해야 할지 모르겠다.

					//	// 새로 추가된 Row의 OID를 읽어들인다.
					//	pRow->ReadData(GetRequestHandle(), true);
					//}

					if(pRow->m_status==DBPENDINGSTATUS_DELETED)
						MakeRowInvalid(this, pRow);
					else
						pRow->m_status = DBPENDINGSTATUS_UNCHANGED;

					if(prgRowStatus && bNotIgnore)
						(*prgRowStatus)[ulCurrentRow] = DBROWSTATUS_S_OK;
					bSucceeded = true;

					// Check if we need to release the row because it's ref was 0
					// See the IRowset::ReleaseRows section in the spec for more
					// information
					if (pRow->m_dwRef == 0)
					{
						pRow->AddRefRow();	// Artifically bump this to remove it
						if( FAILED( RefRows(1, &hRowUpdate, NULL, NULL, false) ) )
							return E_FAIL;
					}
				}
			}
			break;
		}
	}

	// Set the output for rows undone.
	if(pcRows) *pcRows = ulCount;

	if(ulCount==0)
	{
		if(prgRows)
		{
			CoTaskMemFree(*prgRows);
			*prgRows = NULL;
		}

		if(prgRowStatus)
		{
			CoTaskMemFree(*prgRowStatus);
			*prgRowStatus = NULL;
		}
	}
	else if(cRows==0)
	{
		// In the case where cRows == 0, we need to allocate the final
		// array of data.
		if(prgRows && bNotIgnore)
		{
			HROW *prgRowsTemp = (HROW *)CoTaskMemAlloc(ulCount*sizeof(HROW));
			if(prgRowsTemp==NULL) return E_OUTOFMEMORY;
			memcpy(prgRowsTemp, *prgRows, ulCount*sizeof(HROW));
			*prgRows = prgRowsTemp;
		}

		if(prgRowStatus && bNotIgnore)
		{
			DBROWSTATUS *prgRowStatusTemp = (DBROWSTATUS *)CoTaskMemAlloc(ulCount*sizeof(DBROWSTATUS));
			if(prgRowStatusTemp==NULL)
			{
				CoTaskMemFree(*prgRows);
				*prgRows = NULL;
				return E_OUTOFMEMORY;
			}
			memcpy(prgRowStatusTemp, *prgRowStatus, ulCount*sizeof(DBROWSTATUS));
			*prgRowStatus = prgRowStatusTemp;
		}
	}

	DoCommit(this); // commit

	// Send the return value
	if(!bFailed)
		return S_OK;
	else
	{
		return bSucceeded ? DB_S_ERRORSOCCURRED : DB_E_ERRORSOCCURRED;
	}
}
Пример #11
0
STDMETHODIMP CCUBRIDRowset::GetOriginalData(HROW hRow, HACCESSOR hAccessor, void *pData)
{
	ATLTRACE(atlTraceDBProvider, 2, _T("CCUBRIDRowset::GetOriginalData\n"));

	ClearError();
	if(m_nStatus==1) return RaiseError(E_UNEXPECTED, 1, __uuidof(IRowsetUpdate), L"This object is in a zombie state");
	CHECK_RESTART(__uuidof(IRowsetUpdate));

	// 바인딩 정보를 구함
	ATLBINDINGS *pBinding;
	{
		bool bFound = m_rgBindings.Lookup((ULONG)hAccessor, pBinding);
		if(!bFound || pBinding==NULL)
			return DB_E_BADACCESSORHANDLE;
		if(!(pBinding->dwAccessorFlags & DBACCESSOR_ROWDATA))
			return DB_E_BADACCESSORTYPE; // row accessor 가 아니다.
		if(pData==NULL && pBinding->cBindings!=0)
			return E_INVALIDARG;
	}

	// Attempt to locate the row in our map
	CCUBRIDRowsetRow *pRow;
	{
		bool bFound = m_rgRowHandles.Lookup((ULONG)hRow, pRow);
		if(!bFound || pRow==NULL)
			return DB_E_BADROWHANDLE;
	}

	// If the status is DBPENDINGSTATUS_INVALIDROW, the row has been
	// deleted and the change transmitted to the data source.  In 
	// this case, we can't get the original data so return
	// DB_E_DELETEDROW.
	if (pRow->m_status == DBPENDINGSTATUS_INVALIDROW)
		return DB_E_DELETEDROW;

	// Determine if we have a pending insert. In this case, the
	// spec says revert to default values, and if defaults,
	// are not available, then NULLs.

	if (pRow->m_status == DBPENDINGSTATUS_NEW)
	{
		for (ULONG lBind=0; lBind<pBinding->cBindings; lBind++)
		{
			DBBINDING* pBindCur = &(pBinding->pBindings[lBind]);

			// default value가 없으므로 NULL로 set
			if (pBindCur->dwPart & DBPART_VALUE)
				*((BYTE *)pData+pBindCur->obValue) = NULL;
			if (pBindCur->dwPart & DBPART_STATUS)
				*((DBSTATUS*)((BYTE*)(pData) + pBindCur->obStatus)) = DBSTATUS_S_ISNULL;
		}

		return S_OK;
	}

	// 새로 삽입된 Row
	if(pRow->m_iRowset==(ULONG)-1)
	{
		return pRow->WriteData(pBinding, pData, 0);
	}

	DBORDINAL cCols;
	ATLCOLUMNINFO *pInfo = GetColumnInfo(this, &cCols);
	DBROWCOUNT dwBookmark = pRow->m_iRowset+3;//Util::FindBookmark(m_rgBookmarks, (LONG)pRow->m_iRowset+1);

	// 임시 RowClass를 통해 storage에서 데이터를 읽어온 후, pData로 전송한다.
	CCUBRIDRowsetRow OrigRow(m_uCodepage, pRow->m_iRowset, cCols, pInfo, m_spConvert, m_Columns.m_defaultVal);
	OrigRow.ReadData(GetRequestHandle());
	return OrigRow.WriteData(pBinding, pData, dwBookmark);
}
Пример #12
0
STDMETHODIMP CCUBRIDRowset::InsertRow(HCHAPTER hReserved, HACCESSOR hAccessor, void *pData, HROW *phRow)
{
	ATLTRACE(atlTraceDBProvider, 2, "CCUBRIDRowset::InsertRow\n");

	if(phRow) *phRow = NULL;

	if(phRow)
		CHECK_CANHOLDROWS(__uuidof(IRowsetChange));

	ClearError();
	if(m_nStatus==1) return RaiseError(E_UNEXPECTED, 1, __uuidof(IRowsetChange), L"This object is in a zombie state");

	CHECK_UPDATABILITY(DBPROPVAL_UP_INSERT);

	// Determine if we're in immediate or deferred mode
	bool bDeferred = IsDeferred(this);

	// 바인딩 정보를 구함
	ATLBINDINGS *pBinding;
	{
		bool bFound = m_rgBindings.Lookup((ULONG)hAccessor, pBinding);
		if(!bFound || pBinding==NULL)
			return RaiseError(DB_E_BADACCESSORHANDLE, 0, __uuidof(IRowsetChange));
		if(!(pBinding->dwAccessorFlags & DBACCESSOR_ROWDATA))
			return RaiseError(DB_E_BADACCESSORTYPE, 0, __uuidof(IRowsetChange)); // row accessor 가 아니다.
		if(pData==NULL && pBinding->cBindings!=0)
			return RaiseError(E_INVALIDARG, 0, __uuidof(IRowsetChange));
	}

	CCUBRIDRowsetRow *pRow;
	CCUBRIDRowsetRow::KeyType key;
	{	// 새 row를 위한 Row class를 생성한다.
		DBORDINAL cCols;
		ATLCOLUMNINFO *pColInfo = GetColumnInfo(this, &cCols);
		ATLTRY(pRow = new CCUBRIDRowsetRow(m_uCodepage, -1, cCols, pColInfo, m_spConvert, m_Columns.m_defaultVal));
		if(pRow==NULL) return RaiseError(E_OUTOFMEMORY, 0, __uuidof(IRowsetChange));

		// row handle에 추가
		key = (CCUBRIDRowsetRow::KeyType)m_rgRowData.GetCount();
		if (key == 0) key++;
		
		while(m_rgRowHandles.Lookup(key)) key++;
		m_rgRowHandles.SetAt(key, pRow);

		// rowset에 데이터가 하나 늘었다.
//		m_rgRowData.SetCount(m_rgRowData.GetCount()+1);
	}

	HRESULT hrRead = pRow->ReadData(pBinding, pData, m_uCodepage);
	if(FAILED(hrRead))
	{
//		m_rgRowData.SetCount(m_rgRowData.GetCount()-1);
		m_rgRowHandles.RemoveKey(key);
		delete pRow;
		return hrRead;
	}
	pRow->m_status = DBPENDINGSTATUS_NEW;

	if(phRow)
	{	// handle을 반환할 때는 참조 카운트를 하나 증가시킨다.
		pRow->AddRefRow();
		*phRow = (HROW)key;
	}

//	m_rgBookmarks.Add(pRow->m_iRowset+1);

	if(!bDeferred)
	{	// 변화를 지금 적용
		int hConn = GetSessionPtr()->GetConnection();
		UINT uCodepage = GetSessionPtr()->GetCodepage();
		HRESULT hr = pRow->WriteData(hConn, uCodepage, GetRequestHandle(), m_strTableName);
		if(FAILED(hr))
		{
			pRow->ReleaseRow();
			if (phRow != NULL)
				*phRow = NULL;
			return hr;
		}

		pRow->m_status = 0; // or UNCHANGED?
		if(pRow->m_dwRef==0)
		{
			m_rgRowHandles.RemoveKey(key);
			delete pRow;
		}

		DoCommit(this); // commit

		//// deferred update 모드였다가 immediate update 모드로 바뀌지는 않으므로
		//// 다른 NEW 상태의 row는 없다. 즉 m_iRowset을 변경해야 할 row는 없다.

		//// 새로 추가된 Row의 OID를 읽어들인다.
		//pRow->ReadData(GetRequestHandle(), true);
	}

	return hrRead;
}