示例#1
0
//---------------------------------------------------------
bool CPGIS_Shapes_Save::On_Execute(void)
{
	int			SRID;
	CSG_Shapes	*pShapes;
	CSG_String	SQL, Geo_Table, Geo_Type, Geo_Field, sSRID;

	pShapes		= Parameters("SHAPES")	->asShapes();
	Geo_Table	= Parameters("NAME")	->asString();	if( Geo_Table.Length() == 0 )	Geo_Table	= pShapes->Get_Name();
	SRID		= Parameters("SRID")	->asInt();
	SRID		= SG_Get_Projections().Get_SRID_byNamesIndex(SRID);

	sSRID.Printf(SG_T("%d"), SRID);

	//-----------------------------------------------------
	switch( pShapes->Get_Vertex_Type() )
	{
	case SG_VERTEX_TYPE_XY:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point;			Geo_Field	= SG_T("geo_point");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint;		Geo_Field	= SG_T("geo_points");		break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine;		Geo_Field	= SG_T("geo_line");			break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon;	Geo_Field	= SG_T("geo_polygon");		break;
		}
		break;

	case SG_VERTEX_TYPE_XYZ:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point_Z;			Geo_Field	= SG_T("geo_point_z");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint_Z;	Geo_Field	= SG_T("geo_points_z");		break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine_Z;		Geo_Field	= SG_T("geo_line_z");		break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon_Z;	Geo_Field	= SG_T("geo_polygon_z");	break;
		}
		break;

	case SG_VERTEX_TYPE_XYZM:
		switch( pShapes->Get_Type() )
		{	default:	return( false );
		case SHAPE_TYPE_Point:		Geo_Type	= SG_OGIS_TYPE_STR_Point_ZM;		Geo_Field	= SG_T("geo_point_zm");		break;
		case SHAPE_TYPE_Points:		Geo_Type	= SG_OGIS_TYPE_STR_MultiPoint_ZM;	Geo_Field	= SG_T("geo_points_zm");	break;
		case SHAPE_TYPE_Line:		Geo_Type	= SG_OGIS_TYPE_STR_MultiLine_ZM;	Geo_Field	= SG_T("geo_line_zm");		break;
		case SHAPE_TYPE_Polygon:	Geo_Type	= SG_OGIS_TYPE_STR_MultiPolygon_ZM;	Geo_Field	= SG_T("geo_polygon_zm");	break;
		}
		break;
	}

	//-----------------------------------------------------
	if( Get_Connection()->Table_Exists(Geo_Table) )
	{
		Message_Add(CSG_String::Format(SG_T("%s: %s"), _TL("table already exists"), Geo_Table.c_str()));

		switch( Parameters("EXISTS")->asInt() )
		{
		case 0:	// abort export
			return( false );

		case 1:	// replace existing table
			Message_Add(CSG_String::Format(SG_T("%s: %s"), _TL("trying to drop table"), Geo_Table.c_str()));

			if( !Get_Connection()->Table_Drop(Geo_Table, false) )
			{
				Message_Add(CSG_String::Format(SG_T(" ...%s!"), _TL("failed")));

				return( false );
			}

			break;

		case 2:	// append records, if table structure allows
			break;
		}
	}

	//-----------------------------------------------------
	if( !Get_Connection()->Table_Exists(Geo_Table) && !Get_Connection()->Table_Create(Geo_Table, *pShapes, Get_Constraints(Parameters("FLAGS")->asParameters(), pShapes), false) )
	{
		Get_Connection()->Rollback();

		return( false );
	}

	//-----------------------------------------------------
	SQL.Printf(SG_T("SELECT AddGeometryColumn('%s', '%s', %d, '%s', %d)"),
		Geo_Table.c_str(),				// <table_name>
		Geo_Field.c_str(),				// <column_name>
		SRID,							// <srid>
		Geo_Type.Make_Upper().c_str(),	// <type>
		2								// <dimension>
	);

	if( !Get_Connection()->Execute(SQL) )
	{
		Get_Connection()->Rollback();

		Message_Add(_TL("could not create geometry field"));

		return( false );
	}

	//-----------------------------------------------------
	int			iShape, iField, nAdded;
	CSG_String	Insert, Fields, sWKT;

	Fields	= Geo_Field;

	for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
	{
		Fields	+= CSG_String(", ") + pShapes->Get_Field_Name(iField);
	}

	Insert.Printf(SG_T("INSERT INTO %s (%s) VALUES ("), Geo_Table.c_str(), Fields.c_str());

	for(iShape=0, nAdded=0; iShape<pShapes->Get_Count() && Set_Progress(iShape, pShapes->Get_Count()); iShape++)
	{
		CSG_Shape	*pShape	= pShapes->Get_Shape(iShape);

		if( pShape->is_Valid() )
		{
			SQL	= Insert;

			CSG_Shapes_OGIS_Converter::to_WKText(pShape, sWKT);

			SQL	+= SG_T("GeomFromText('") + sWKT + SG_T("', ") + sSRID + SG_T(")");

			for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
			{
				CSG_String	s = pShape->asString(iField);

				if( pShapes->Get_Field_Type(iField) == SG_DATATYPE_String )
				{
					s.Replace(SG_T("'"), SG_T("\""));
					s	= SG_T("'") + s + SG_T("'");
				}

				SQL	+= SG_T(", ")  + s;
			}

			SQL	+= SG_T(")");

			if( Get_Connection()->Execute(SQL) )
			{
				nAdded++;
			}
			else
			{
				Message_Add(CSG_String::Format(SG_T("dropped %d. shape"), iShape));
			}
		}
	}

	//-----------------------------------------------------
	if( nAdded == 0 )
	{
		Get_Connection()->Rollback();

		Get_Connection()->Table_Drop(Geo_Table);

		return( false );
	}

	return( Get_Connection()->Commit() );
}
//---------------------------------------------------------
bool CShapes_Save::On_Execute(void)
{
	if( !Get_Connection()->has_PostGIS() )
	{
		Error_Set(_TL("not a valid PostGIS database!"));

		return( false );
	}

	//-----------------------------------------------------
	CSG_Shapes	*pShapes;
	CSG_String	SQL, Name, Type, Field, SavePoint;

	pShapes		= Parameters("SHAPES")->asShapes();
	Name		= Parameters("NAME"  )->asString();	if( Name.Length() == 0 )	Name	= pShapes->Get_Name();

	Field		= "geometry";

	int	SRID	= Get_SRID();

	//-----------------------------------------------------
	if( !CSG_Shapes_OGIS_Converter::from_ShapeType(Type, pShapes->Get_Type(), pShapes->Get_Vertex_Type()) )
	{
		Error_Set(_TL("invalid or unsupported shape or vertex type"));

		return( false );
	}

	//-----------------------------------------------------
	Get_Connection()->Begin(SavePoint = Get_Connection()->is_Transaction() ? "SHAPES_SAVE" : "");

	//-----------------------------------------------------
	if( Get_Connection()->Table_Exists(Name) )
	{
		Message_Add(_TL("table already exists") + CSG_String(": ") + Name);

		switch( Parameters("EXISTS")->asInt() )
		{
		case 0:	// abort export
			return( false );

		case 1:	// replace existing table
			Message_Add(_TL("trying to drop table") + CSG_String(": ") + Name);

			if( !Get_Connection()->Table_Drop(Name, false) )
			{
				Message_Add(CSG_String(" ...") + _TL("failed") + "!");

				return( false );
			}

			break;

		case 2:	// append records, if table structure allows
			break;
		}
	}

	//-----------------------------------------------------
	if( !Get_Connection()->Table_Exists(Name) )
	{
		if( !Get_Connection()->Table_Create(Name, *pShapes, Get_Constraints(&Parameters, "SHAPES"), false) )
		{
			Error_Set(_TL("could not create table"));

			Get_Connection()->Rollback(SavePoint);

			return( false );
		}

		//-------------------------------------------------
		// SELECT AddGeometryColumn(<table_name>, <column_name>, <srid>, <type>, <dimension>)

		SQL.Printf(SG_T("SELECT AddGeometryColumn('%s', '%s', %d, '%s', %d)"),
			Name.c_str(), Field.c_str(), SRID, Type.c_str(),
			pShapes->Get_Vertex_Type() == SG_VERTEX_TYPE_XY  ? 2 :
			pShapes->Get_Vertex_Type() == SG_VERTEX_TYPE_XYZ ? 3 : 4
		);

		if( !Get_Connection()->Execute(SQL) )
		{
			Error_Set(_TL("could not create geometry field"));

			Get_Connection()->Rollback(SavePoint);

			return( false );
		}
	}

	//-----------------------------------------------------
	bool	bBinary	= Get_Connection()->has_Version(9);

	int		iShape, iField, nAdded;

	CSG_String	Insert	= "INSERT INTO \"" + Name + "\" (" + Field;

	for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
	{
		Insert	+= CSG_String(", ") + pShapes->Get_Field_Name(iField);
	}

	Insert	+= ") VALUES (";

	//-----------------------------------------------------
	for(iShape=0, nAdded=0; iShape==nAdded && iShape<pShapes->Get_Count() && Set_Progress(iShape, pShapes->Get_Count()); iShape++)
	{
		CSG_Shape	*pShape	= pShapes->Get_Shape(iShape);

		if( pShape->is_Valid() )
		{
			SQL	= Insert;

			if( bBinary )
			{
				CSG_Bytes	WKB;

				CSG_Shapes_OGIS_Converter::to_WKBinary(pShape, WKB);

				SQL	+= "ST_GeomFromWKB(E'\\\\x" + WKB.toHexString() + CSG_String::Format("', %d)", SRID);
			}
			else
			{
				CSG_String	WKT;

				CSG_Shapes_OGIS_Converter::to_WKText(pShape, WKT);

				SQL	+= "ST_GeomFromText('" + WKT + CSG_String::Format("', %d)", SRID);
			}

			for(iField=0; iField<pShapes->Get_Field_Count(); iField++)
			{
				CSG_String	s = pShape->asString(iField);

				if( pShapes->Get_Field_Type(iField) == SG_DATATYPE_String )
				{
					if( 1 )
					{
						char	*_s	= NULL; if( s.to_ASCII(&_s) ) s = _s; SG_FREE_SAFE(_s);
					}

					s.Replace("'", "\"");

					s	= "'" + s + "'";
				}

				SQL	+= ", "  + s;
			}

			SQL	+= ")";

			if( Get_Connection()->Execute(SQL) )
			{
				nAdded++;
			}
			else
			{
				Message_Add(CSG_String::Format("%s [%d/%d]", _TL("could not save shape"), 1 + iShape, pShapes->Get_Count()));
			}
		}
	}

	//-----------------------------------------------------
	if( nAdded < pShapes->Get_Count() )
	{
		Message_Add(SQL);

		Get_Connection()->Rollback(SavePoint);

		return( false );
	}

	Get_Connection()->Commit(SavePoint);

	Get_Connection()->GUI_Update();

	Get_Connection()->Add_MetaData(*pShapes, Name);

	pShapes->Set_Modified(false);

	return( true );
}