Beispiel #1
0
CPLErr SDEDataset::ComputeRasterInfo() {
    long nSDEErr;
    SE_RASTERINFO raster;

    nSDEErr = SE_rasterinfo_create(&raster);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rasterinfo_create" );
        return CE_Fatal;
    }

    LONG nRasterColumnId = 0;

    nSDEErr = SE_rascolinfo_get_id( hRasterColumn,
                                    &nRasterColumnId);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" );
        return CE_Fatal;
    }

    nSDEErr = SE_raster_get_info_by_id( hConnection,
                                        nRasterColumnId,
                                        1,
                                        raster);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" );
        return CE_Fatal;
    }

    LONG nBandsRet;
    nSDEErr = SE_raster_get_bands(  hConnection,
                                    raster,
                                    &paohSDERasterBands,
                                    &nBandsRet);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_raster_get_bands" );
        return CE_Fatal;
    }

    nBands = nBandsRet;

    SE_RASBANDINFO band;

    // grab our other stuff from the first band and hope for the best
    band = paohSDERasterBands[0];

    LONG nXSRet, nYSRet;
    nSDEErr = SE_rasbandinfo_get_band_size( band, &nXSRet, &nYSRet );
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" );
        return CE_Fatal;
    }

    nRasterXSize = nXSRet;
    nRasterYSize = nYSRet;

    SE_ENVELOPE extent;
    nSDEErr = SE_rasbandinfo_get_extent(band, &extent);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rasbandinfo_get_extent" );
        return CE_Fatal;
    }
    dfMinX = extent.minx;
    dfMinY = extent.miny;
    dfMaxX = extent.maxx;
    dfMaxY = extent.maxy;

    CPLDebug("SDERASTER", "minx: %.5f, miny: %.5f, maxx: %.5f, maxy: %.5f", dfMinX, dfMinY, dfMaxX, dfMaxY);

    // x0 roughly corresponds to dfMinX
    // y0 roughly corresponds to dfMaxY
    // They can be different than the extent parameters because
    // SDE uses offsets.  The following info is from Duarte Carreira
    // in relation to bug #2063 http://trac.osgeo.org/gdal/ticket/2063 :

    // Depending on how the data was loaded, the pixel width
    // or pixel height may include a pixel offset from the nearest
    // tile boundary. An offset will be indicated by aplus sign
    // "+" followed by a value. The value indicates the number
    // of pixels the nearest tile boundary is to the left of
    // the image for the x dimension or the number of
    // pixels the nearest tile boundary is above the image for
    // the y dimension. The offset information is only useful
    // for advanced application developers who need to know
    // where the image begins in relation to the underlying tile structure

    LFLOAT x0, y0;
    nSDEErr = SE_rasbandinfo_get_tile_origin(band, &x0, &y0);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rasbandinfo_get_tile_origin" );
        return CE_Fatal;
    }
    CPLDebug("SDERASTER", "Tile origin: %.5f, %.5f", x0, y0);

    // we also need to adjust dfMaxX and dfMinY otherwise the cell size will change
    dfMaxX = (x0-dfMinX) + dfMaxX;
    dfMinY = (y0-dfMaxY) + dfMinY;

    // adjust the bbox based on the tile origin.
    dfMinX = MIN(x0, dfMinX);
    dfMaxY = MAX(y0, dfMaxY);

    nSDEErr = SE_rasterattr_create(&hAttributes, false);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_rasterattr_create" );
        return CE_Fatal;
    }

    // Grab the pointer for our member variable

    nSDEErr = SE_stream_create(hConnection, &hStream);
    if( nSDEErr != SE_SUCCESS )
    {
        IssueSDEError( nSDEErr, "SE_stream_create" );
        return CE_Fatal;
    }


    for (int i=0; i < nBands; i++) {
        SetBand( i+1, new SDERasterBand( this, i+1, -1, &(paohSDERasterBands[i]) ));
    }

    GDALRasterBand* b = GetRasterBand(1);

    eDataType = b->GetRasterDataType();

    SE_rasterinfo_free(raster);

    return CE_None;
}
/// <summary>Executes the release lock command, returning an FdoILockConflictReader.</summary>
/// <returns>Returns an FdoILockConflictReader</returns> 
FdoILockConflictReader* ArcSDEReleaseLockCommand::Execute ()
{
    const CHAR* columns[1];
    FdoPtr<ArcSDEConnection> connection;
    CHAR table[SE_QUALIFIED_TABLE_NAME];
    CHAR column[SE_MAX_COLUMN_LEN];
    wchar_t* wcolumn;
    CHAR *where;
    SHORT count;
    SE_FILTER* filters;
    FdoString* property;
    LONG result;
    SE_STREAM stream;
    CHAR user_name[SE_MAX_OWNER_LEN];
    wchar_t* me;
    CHAR logfile[SE_MAX_PATH_LEN];
    SE_SQL_CONSTRUCT  sql_construct;
    CHAR* tables[1];
    FdoPtr<FdoISQLDataReader> reader;
    SE_LOG log;
    LONG number = 0;
    Lock* locks = NULL;
    wchar_t* locktable = NULL;
    FdoPtr<ArcSDELockConflictReader> ret;

    // verify the connection
    connection = static_cast<ArcSDEConnection*>(GetConnection ());
    if (connection == NULL)
        throw FdoException::Create (NlsMsgGet (ARCSDE_CONNECTION_NOT_ESTABLISHED, "Connection not established."));

    // verify the feature class name is specified
    if (mClassName == NULL)
        throw FdoException::Create (NlsMsgGet (ARCSDE_FEATURE_CLASS_UNSPECIFIED, "Feature class name not specified."));

    // get the class definition which reflects the requested feature class name
    FdoPtr<FdoClassDefinition> definition = connection->GetRequestedClassDefinition (mClassName);

    // get the filter if any
    FdoPtr<FdoFilter> filter = GetFilter ();

    // get SQL query's "from" table list
    mConnection->ClassToTable (table, definition);

    // ensure lockable table
    if (!ArcSDELockUtility::IsLockable (connection->GetConnection (), table, column))
    {
        wchar_t* wtable;
        sde_multibyte_to_wide (wtable, table);
        throw FdoException::Create (NlsMsgGet1 (ARCSDE_LOCKING_NOT_ENABLED, "Table '%1$ls' is not lock enabled.", wtable));
    }

    // get the property name that is the row_id
    sde_multibyte_to_wide (wcolumn, column);
    property = connection->ColumnToProperty (definition, wcolumn);

    // get SQL query's "where" clause & spatial filters
    where = NULL;
    count = 0;
    filters = NULL;
    GetFilterInfo (connection, filter, definition, where, count, filters);

    // establish an empty conflict reader
    ret = new ArcSDELockConflictReader (connection, definition->GetQualifiedName (), table, property);

    // initialize the stream query
    result = SE_stream_create (connection->GetConnection (), &stream);
    handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_ALLOC, "Cannot initialize SE_STREAM structure.");

    // if necessary, version enable the stream
    ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

    // release lock, don't return rows
    result = SE_connection_get_user_name (connection->GetConnection (), user_name);
    handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_USER_UNKNOWN, "Cannot determine current user.");
    sde_multibyte_to_wide (me, user_name);
    if (0 == wcscmp (GetLockOwner (), L""))
    {
        result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_UNLOCK_ON_QUERY
        | SE_ROWLOCKING_LOCK_ONLY);
        handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");
    }
    else if (0 == wcscmp (GetLockOwner (), me))
    {
        result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_UNLOCK_ON_QUERY
        | SE_ROWLOCKING_FILTER_MY_LOCKS | SE_ROWLOCKING_LOCK_ONLY);
        handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");
    }
    else
    {
        LONG *ids = NULL;
        CHAR **users = NULL;
        CHAR lt[SE_QUALIFIED_TABLE_NAME];

        if (0)
            throw FdoCommandException::Create (NlsMsgGet (ARCSDE_RELEASE_UNOWNED_LOCKS, "Releasing other owners locks is not supported."));

        result = SE_table_get_rowlocks (connection->GetConnection(), table, &number, &ids, &users);
        handle_sde_err<FdoCommandException>(connection->GetConnection(), result, __FILE__, __LINE__, ARCSDE_GET_ROW_LOCK_LIST_FAILED, "Failed to get the row lock list.");
        if (0 != number)
        {
            // put the id's and users in an array of lock structures
            locks = (Lock*)calloc (number, sizeof (Lock));
            for (int i = 0; i < number; i++)
            {
                locks[i].id = ids[i];
                sde_strcpy (sde_pus2wc(locks[i].user), sde_pcus2wc(users[i]));
            }
            qsort (locks, number, sizeof (LONG), compare);
            ArcSDELockUtility::LockTableName (lt, connection, table);
            sde_multibyte_to_wide (locktable, lt);
            SE_table_free_rowlocks_list (number, ids, users);
        }
    }

    // apply attribute and spatial query to stream
    columns[0] = column;
    ApplyFilterInfoToStream (connection, stream, table, where, 1, columns, count, filters);

    // set up a temporary log file
    mConnection->MakeLog (&log, table);

    // accumulate the query in the log file
    result = SE_stream_set_logfile (stream, log, FALSE);
    handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_LOG_SET_LOGFILE, "Could not set log file.");

    // lock the table's lock table to prevent alteration
    reader = ArcSDELockUtility::LockLockTable (mConnection, table);

    // actually execute the query
    result = SE_stream_execute (stream);
    handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");

    result = SE_stream_fetch (stream);
    // three possibilities: locks for the specified user exist (SE_SUCCESS) and the log file isn't filled,
    // everything was unlocked (SE_FINISHED)
    // or there was a conflict (SE_LOCK_CONFLICT)
    switch (result)
    {
        case SE_SUCCESS:
            if (0 != number)
            {
                CHAR* user;
                LONG id;
                wchar_t drop[1024];
                FdoPtr<FdoISQLCommand> sql;
                Lock key;
                Lock* item;

		// Get lock owner name:
		const wchar_t *wLockOwner = GetLockOwner();
		wchar_t *wLockOwnerUpr = (wchar_t*)alloca( (1+wcslen(wLockOwner)) * sizeof(wchar_t));
		wcscpy(wLockOwnerUpr, wLockOwner);
		FdoCommonOSUtil::wcsupr(wLockOwnerUpr);  // ToDo: Oracle-specific
                sde_wide_to_multibyte (user, wLockOwnerUpr);

                // process each row returned (ignoring the log file)
                sql = (FdoISQLCommand*)connection->CreateCommand (FdoCommandType_SQLCommand);
                do
                {
                    if (SE_SUCCESS != (result = SE_stream_get_integer (stream, 1, &id)))
                    {
                        sde_multibyte_to_wide (wcolumn, column);
                        handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_GET, "Stream get ('%1$ls') failed for column '%2$ls'.", L"SE_stream_get_integer", wcolumn);
                    }
                    else
                    {
                        key.id = id;
                        // look it up to see if it's a conflict (i.e. not found)
                        if (NULL != (item = (Lock*)bsearch (&key, locks, number, sizeof (LONG), compare)))
                        {
                            if (0 == sde_strcmp (sde_pcus2wc(user), sde_pcus2wc(item->user)))
                            {
                                // ToDo: optimize this singleton delete somewhat
                                //ROW_ID                                    NOT NULL NUMBER(38)
                                //USER_NAME                                 NOT NULL VARCHAR2(32)
                                FdoCommonOSUtil::swprintf (drop, ELEMENTS (drop), L"delete from %ls where user_name=upper('%ls') and row_id = %ld", locktable, GetLockOwner (), id);
                                sql->SetSQLStatement (drop);
                                sql->ExecuteNonQuery ();
                            }
                            else
                                ret->AddIdentity (id);
                        }
                        else
                        {
                            // no lock, hence no conflict
                        }
                    }
                }
                while (SE_SUCCESS == (result = SE_stream_fetch (stream)));
                if (SE_FINISHED != result)
                    handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_FETCH, "Stream fetch failed.");
            }
            break;
        case SE_FINISHED:
            break;
        case SE_LOCK_CONFLICT:
            // reuse the same stream
            result = SE_stream_close (stream, TRUE);

            // if necessary, version enable the stream
            ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

            // select locks still remaining
            result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_FILTER_OTHER_LOCKS);
            handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");

            // get the list of row ids from the log file
            tables[0] = table;
            sql_construct.tables = tables;
            sql_construct.num_tables = ELEMENTS (tables);
            sql_construct.where = NULL;
            ArcSDELockUtility::GetLogFile (logfile, connection->GetConnection (), log);
            result = SE_stream_query_logfile (stream, logfile, 1, columns, &sql_construct);
            handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_LOG_FILE_QUERY, "Unable to query log file.");

            // execute the query that fetches conflicts
            result = SE_stream_execute (stream);
            handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");

            // gather the conflicts
            ArcSDELockUtility::GatherConflicts (stream, column, 1, ret);

            // if there were conflicts (and there will be), do a partial unlock
            if (0 != ret->mIds->GetCount ())
            {
                // reuse the same stream
                result = SE_stream_close (stream, TRUE);

                // if necessary, version enable the stream
                ArcSDELongTransactionUtility::VersionStream (connection, stream, table, false);

                // select locks still remaining
                result = SE_stream_set_rowlocking (stream, SE_ROWLOCKING_FILTER_MY_LOCKS | SE_ROWLOCKING_UNLOCK_ON_QUERY | SE_ROWLOCKING_LOCK_ONLY);
                handle_sde_err<FdoCommandException> (connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_LOCK, "Cannot set row locking on the stream.");

                // get the list of row ids from the log file
                result = SE_stream_query_logfile (stream, logfile, 1, columns, &sql_construct);
                handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_LOG_FILE_QUERY, "Unable to query log file.");

                // execute the query that unlocks rows
                result = SE_stream_execute (stream);
                handle_sde_err<FdoCommandException>(stream, result, __FILE__, __LINE__, ARCSDE_STREAM_EXECUTE, "Stream execute failed.");
            }
            else
                throw FdoException::Create (NlsMsgGet(ARCSDE_UNEXPECTED_ERROR, "Unexpected error encountered in ArcSDE Provider."));
            break;
        default:
            handle_sde_err<FdoCommandException> (stream, result, __FILE__, __LINE__, ARCSDE_STREAM_FETCH, "Stream fetch failed.");
    }

    // release the transaction lock
    if (reader != NULL)
        reader->Close ();

    // clean up
    if (NULL != locks)
        free(locks);
    result = SE_stream_free (stream);
    handle_sde_err<FdoCommandException>(connection->GetConnection (), result, __FILE__, __LINE__, ARCSDE_STREAM_FREE, "Stream free failed.");
    delete[] where;
    if (NULL != filters)
    {
        for (int i = 0; i < count; i++)
            if (NULL != filters[i].filter.shape)
                SE_shape_free (filters[i].filter.shape);
        delete[] filters;
    }

    return (FDO_SAFE_ADDREF (ret.p));
}