STDMETHODIMP CSimplePointDatasetHelper::get_Bounds(IEnvelope **Bounds)
{
	HRESULT hr;
	if (! Bounds) return E_POINTER;

  // Get an envelope for the extent of the dataset
  // We will have to calculate the extent by opening a cursor
  // on the dataset, and building up a minimum bounding rectangle 
  
  // Prepare to open a cursor.
  // Make the fieldmap, with values of -1 (attributes do not need fetching)

	long lNumFields;
	IFieldsPtr ipFields;
	
	hr = get_Fields(0, &ipFields);
	if (FAILED(hr)) return hr;

	hr = ipFields->get_FieldCount(&lNumFields);
	if (FAILED(hr)) return hr;

	CComVariant vFieldMap;
	vFieldMap.vt = VT_ARRAY | VT_I4;
  vFieldMap.parray = ::SafeArrayCreateVector(VT_I4, 0, lNumFields);
  long HUGEP *pMap = 0; // raw pointer to array
  hr = SafeArrayAccessData(vFieldMap.parray, (void HUGEP **)&pMap);
  if (FAILED(hr)) return hr;
	long i;
	for (i=0; i < lNumFields; i++)
		pMap[i] = -1;
	SafeArrayUnaccessData(vFieldMap.parray);  

	// Open the cursor
  IPlugInCursorHelperPtr ipPlugInCursor;
  hr = FetchAll(0, L"", vFieldMap, &ipPlugInCursor);
	if (FAILED(hr)) return hr;

	// loop through the data recording min/max X and Y values.
	double dxMin =  9999999;
  double dxMax = -9999999;
  double dyMin =  9999999;
  double dyMax = -9999999;
	double x,y;

	VARIANT_BOOL bEOF = VARIANT_FALSE;
	IGeometryPtr ipGeom;
	hr = ipGeom.CreateInstance(CLSID_Point);
	if (FAILED(hr)) return hr;

  IPointPtr ipPoint;

	long lNumRecords = 0;
  do
	{
		lNumRecords++;
		hr = ipPlugInCursor->QueryShape(ipGeom);
    if (FAILED(hr)) return hr;
    
		ipPoint = ipGeom;
		if (ipPoint == NULL) return E_FAIL;
    hr = ipPoint->QueryCoords(&x, &y);
		if (FAILED(hr)) return hr;

    if (x > dxMax) dxMax = x;
		if (x < dxMin) dxMin = x;
    if (y > dyMax) dyMax = y;
		if (y < dyMin) dyMin = y;

		hr = ipPlugInCursor->NextRecord();
		if (hr != S_OK)
		{
			hr = ipPlugInCursor->IsFinished(&bEOF);
      if (FAILED(hr)) return hr;
		}
	} while (!bEOF);

  // Handle special case of single point in file
  // - add a small amount, so that we will end up with an envelope rather than a point
  if (lNumRecords == 1)
	{
	  double dDelta = 0.01;
		if (dxMax != 0) 
			dDelta = dxMax / 1000;
    dxMax += dDelta;
		dyMax += dDelta;
	}

	// Create the envelope object, setting the appropriate spatial reference
  IEnvelopePtr ipEnv;
	hr = ipEnv.CreateInstance(CLSID_Envelope);
	if (FAILED(hr)) return hr;

	ISpatialReferencePtr ipSR;
	hr = ipSR.CreateInstance(CLSID_UnknownCoordinateSystem);
  if (FAILED(hr)) return hr;

	hr = ipEnv->putref_SpatialReference(ipSR);
	if (FAILED(hr)) return hr;

  hr = ipEnv->PutCoords(dxMin, dyMin, dxMax, dyMax);
	if (FAILED(hr)) return hr;

  *Bounds = ipEnv.Detach(); // pass ownership of object to client
	
	return S_OK;
}
Exemplo n.º 2
0
bool ODBCConnection::Execute()
{
	LLOG("Execute " << (void *)this << " " << (void *)session << " " << statement);
	if(session->hstmt == SQL_NULL_HANDLE)
		return false;
	session->FlushConnections();
	last_insert_table.Clear();
	number.Clear();
	text.Clear();
	time.Clear();
	CParser p(statement);
	if((p.Id("insert") || p.Id("INSERT")) && (p.Id("into") || p.Id("INTO")) && p.IsId())
		last_insert_table = p.ReadId();

	String query;
	int pi = 0;
	const char *s = statement;
	while(s < statement.End())
		if(*s == '\'' || *s == '\"')
			s = ODBCReadString(s, query);
		else {
			if(*s == '?') {
				if(pi >= param.GetCount()) {
					session->SetError("Invalid number of parameters", statement);
					return false;
				}
				Value v = param[pi++];
				if(v.GetType() == 34)
					query.Cat(SqlCompile(MSSQL, ~SqlBinary(SqlRaw(v))));
				else
					query.Cat(SqlCompile(MSSQL, ~SqlVal(v)));
			}
			else
				query.Cat(*s);
			s++;
		}
	param.Clear();
	if(!IsOk(SQLPrepare(session->hstmt, (SQLCHAR *)~query, query.GetCount())))
		return false;

/*
	}
	else {
		if(!IsOk(SQLPrepare(session->hstmt, (SQLCHAR *)~statement, statement.GetCount())))
			return false;
		parse = false;
		bparam = pick(param);
		param.Clear();
		for(int i = 0; i < bparam.GetCount(); i++) {
			Param& p = bparam[i];
			if(!IsOk(SQLBindParameter(session->hstmt, i + 1, SQL_PARAM_INPUT, p.ctype, p.sqltype,
			                          p.width, 0, (SQLPOINTER)~p.data, p.data.GetLength(), &p.li)))
				return false;
		}
	}
*/
	SQLSMALLINT ncol;
	if(!IsOk(SQLExecute(session->hstmt)) || !IsOk(SQLNumResultCols(session->hstmt, &ncol))) {
		SQLFreeStmt(session->hstmt, SQL_CLOSE);
		return false;
	}
	info.Clear();
	string_type.Clear();
	for(int i = 1; i <= ncol; i++) {
		SQLCHAR      ColumnName[256];
		SQLSMALLINT  NameLength;
		SQLSMALLINT  DataType;
		SQLULEN      ColumnSize;
		SQLSMALLINT  DecimalDigits;
		SQLSMALLINT  Nullable;
		if(!IsOk(SQLDescribeCol(session->hstmt, i, ColumnName, 255, &NameLength, &DataType,
		                        &ColumnSize, &DecimalDigits, &Nullable)))
			return false;
		string_type.Add(SQL_C_CHAR);
		SqlColumnInfo& f = info.Add();
		f.nullable = Nullable != SQL_NO_NULLS;
		f.binary = false;
		f.precision = DecimalDigits;
		f.scale = 0;
		f.width = ColumnSize;
		f.name = (char *)ColumnName;
		switch(DataType) {
		case SQL_DECIMAL:
		case SQL_NUMERIC:
		case SQL_SMALLINT:
		case SQL_INTEGER:
		case SQL_REAL:
		case SQL_FLOAT:
		case SQL_DOUBLE:
		case SQL_BIT:
		case SQL_TINYINT:
			f.type = DOUBLE_V;
			break;
		case SQL_BIGINT:
			f.type = INT64_V;
			break;
		case SQL_TYPE_DATE:
			f.type = DATE_V;
			break;
		case SQL_TYPE_TIMESTAMP:
			f.type = TIME_V;
			break;
		case SQL_BINARY:
		case SQL_VARBINARY:
		case SQL_LONGVARBINARY:
			f.type = STRING_V;
			f.binary = true;
			string_type.Top() = SQL_C_BINARY;
			break;
		case SQL_WCHAR:
		case SQL_WVARCHAR:
		case SQL_WLONGVARCHAR:
			f.type = STRING_V;
			f.binary = true;
			string_type.Top() = SQL_C_WCHAR;
			break;
		default:
			f.type = STRING_V;
			break;
		}
	}
	SQLLEN rc;
	SQLRowCount(session->hstmt, &rc);
	rowsprocessed = rc;
	FetchAll();
	return true;
}