PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ postgis_valid_typmod()

GSERIALIZED * postgis_valid_typmod ( GSERIALIZED gser,
int32_t  typmod 
)

Check the consistency of the metadata we want to enforce in the typmod: srid, type and dimensionality.

If things are inconsistent, shut down the query.

Definition at line 110 of file gserialized_typmod.c.

111{
112 int32 geom_srid = gserialized_get_srid(gser);
113 int32 geom_type = gserialized_get_type(gser);
114 int32 geom_z = gserialized_has_z(gser);
115 int32 geom_m = gserialized_has_m(gser);
116 int32 typmod_srid = TYPMOD_GET_SRID(typmod);
117 int32 typmod_type = TYPMOD_GET_TYPE(typmod);
118 int32 typmod_z = TYPMOD_GET_Z(typmod);
119 int32 typmod_m = TYPMOD_GET_M(typmod);
120
121 POSTGIS_DEBUG(2, "Entered function");
122
123 /* No typmod (-1) => no preferences */
124 if (typmod < 0) return gser;
125
126 POSTGIS_DEBUGF(3, "Got geom(type = %d, srid = %d, hasz = %d, hasm = %d)", geom_type, geom_srid, geom_z, geom_m);
127 POSTGIS_DEBUGF(3, "Got typmod(type = %d, srid = %d, hasz = %d, hasm = %d)", typmod_type, typmod_srid, typmod_z, typmod_m);
128
129 /*
130 * #3031: If a user is handing us a MULTIPOINT EMPTY but trying to fit it into
131 * a POINT geometry column, there's a strong chance the reason she has
132 * a MULTIPOINT EMPTY because we gave it to her during data dump,
133 * converting the internal POINT EMPTY into a EWKB MULTIPOINT EMPTY
134 * (because EWKB doesn't have a clean way to represent POINT EMPTY).
135 * In such a case, it makes sense to turn the MULTIPOINT EMPTY back into a
136 * point EMPTY, rather than throwing an error.
137 */
138 if ( typmod_type == POINTTYPE && geom_type == MULTIPOINTTYPE &&
140 {
141 LWPOINT *empty_point = lwpoint_construct_empty(geom_srid, geom_z, geom_m);
142 geom_type = POINTTYPE;
143 pfree(gser);
144 if ( gserialized_is_geodetic(gser) )
145 gser = geography_serialize(lwpoint_as_lwgeom(empty_point));
146 else
147 gser = geometry_serialize(lwpoint_as_lwgeom(empty_point));
148 }
149
150 /* Typmod has a preference for SRID, but geometry does not? Harmonize the geometry SRID. */
151 if ( typmod_srid > 0 && geom_srid == 0 )
152 {
153 gserialized_set_srid(gser, typmod_srid);
154 geom_srid = typmod_srid;
155 }
156
157 /* Typmod has a preference for SRID? Geometry SRID had better match. */
158 if ( typmod_srid > 0 && typmod_srid != geom_srid )
159 {
160 ereport(ERROR, (
161 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
162 errmsg("Geometry SRID (%d) does not match column SRID (%d)", geom_srid, typmod_srid) ));
163 }
164
165 /* Typmod has a preference for MULTI* geometry type */
166 /* and geometry is the singleton type. */
167 if ( typmod_type > 0 && typmod_type == lwtype_multitype(geom_type) )
168 {
169 /* Promote the singleton to equivalent multi */
170 LWGEOM *geom = lwgeom_from_gserialized(gser);
171 LWGEOM *mgeom = lwgeom_as_multi(geom);
172 GSERIALIZED *mgser = gserialized_is_geodetic(gser) ?
173 geography_serialize(mgeom) :
174 geometry_serialize(mgeom);
175 /* Count on caller memory context cleaning up dangling gserialized */
176 gser = mgser;
177 geom_type = gserialized_get_type(gser);
178 lwgeom_free(geom);
179 lwgeom_free(mgeom);
180 }
181
182 /* Typmod has a preference for geometry type. */
183 if ( typmod_type > 0 &&
184 /* GEOMETRYCOLLECTION column can hold any kind of collection */
185 ((typmod_type == COLLECTIONTYPE && ! (geom_type == COLLECTIONTYPE ||
186 geom_type == MULTIPOLYGONTYPE ||
187 geom_type == MULTIPOINTTYPE ||
188 geom_type == MULTILINETYPE )) ||
189 /* Other types must be strictly equal. */
190 (typmod_type != geom_type)) )
191 {
192 ereport(ERROR, (
193 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
194 errmsg("Geometry type (%s) does not match column type (%s)", lwtype_name(geom_type), lwtype_name(typmod_type)) ));
195 }
196
197 /* Mismatched Z dimensionality. */
198 if ( typmod_z && ! geom_z )
199 {
200 ereport(ERROR, (
201 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
202 errmsg("Column has Z dimension but geometry does not" )));
203 }
204
205 /* Mismatched Z dimensionality (other way). */
206 if ( geom_z && ! typmod_z )
207 {
208 ereport(ERROR, (
209 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
210 errmsg("Geometry has Z dimension but column does not" )));
211 }
212
213 /* Mismatched M dimensionality. */
214 if ( typmod_m && ! geom_m )
215 {
216 ereport(ERROR, (
217 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
218 errmsg("Column has M dimension but geometry does not" )));
219 }
220
221 /* Mismatched M dimensionality (other way). */
222 if ( geom_m && ! typmod_m )
223 {
224 ereport(ERROR, (
225 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
226 errmsg("Geometry has M dimension but column does not" )));
227 }
228
229 return gser;
230
231}
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_is_geodetic(const GSERIALIZED *g)
Check if a GSERIALIZED is a geography.
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int gserialized_has_m(const GSERIALIZED *g)
Check if a GSERIALIZED has an M ordinate.
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
void gserialized_set_srid(GSERIALIZED *g, int32_t srid)
Write the SRID into the serialized form (it is packed into three bytes so this is a handy function).
int gserialized_has_z(const GSERIALIZED *g)
Check if a GSERIALIZED has a Z ordinate.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define TYPMOD_GET_SRID(typmod)
Macros for manipulating the 'typemod' int.
Definition liblwgeom.h:192
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
#define COLLECTIONTYPE
Definition liblwgeom.h:108
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition lwgeom.c:408
#define MULTILINETYPE
Definition liblwgeom.h:106
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define TYPMOD_GET_M(typmod)
Definition liblwgeom.h:198
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
uint8_t lwtype_multitype(uint8_t type)
Definition lwgeom.c:398
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoint.c:151
#define TYPMOD_GET_TYPE(typmod)
Definition liblwgeom.h:194
#define TYPMOD_GET_Z(typmod)
Definition liblwgeom.h:196
unsigned int int32
Definition shpopen.c:54

References COLLECTIONTYPE, gserialized_get_srid(), gserialized_get_type(), gserialized_has_m(), gserialized_has_z(), gserialized_is_empty(), gserialized_is_geodetic(), gserialized_set_srid(), lwgeom_as_multi(), lwgeom_free(), lwgeom_from_gserialized(), lwpoint_as_lwgeom(), lwpoint_construct_empty(), lwtype_multitype(), lwtype_name(), MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, POINTTYPE, TYPMOD_GET_M, TYPMOD_GET_SRID, TYPMOD_GET_TYPE, and TYPMOD_GET_Z.

Referenced by geography_enforce_typmod(), geometry_enforce_typmod(), gserialized_geography_from_lwgeom(), LWGEOM_in(), and LWGEOM_recv().

Here is the call graph for this function:
Here is the caller graph for this function: