summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--Docs/gis.txt861
-rw-r--r--client/mysql.cc1
-rw-r--r--client/mysqlimport.c2
-rw-r--r--client/mysqlshow.c2
-rw-r--r--include/Makefile.am2
-rw-r--r--include/m_ctype.h3
-rw-r--r--include/my_xml.h61
-rw-r--r--include/mysql.h2
-rw-r--r--include/mysqld_error.h3
-rw-r--r--libmysql/Makefile.shared2
-rw-r--r--libmysql/libmysql.c483
-rw-r--r--mysql-test/r/create.result71
-rw-r--r--mysql-test/r/derived.result6
-rw-r--r--mysql-test/r/func_crypt.result11
-rw-r--r--mysql-test/r/func_str.result3
-rw-r--r--mysql-test/r/multi_update.result15
-rw-r--r--mysql-test/r/query_cache.result1
-rw-r--r--mysql-test/r/rpl_temporary.result74
-rw-r--r--mysql-test/r/subselect.result150
-rw-r--r--mysql-test/r/update.result5
-rw-r--r--mysql-test/t/create.test41
-rw-r--r--mysql-test/t/derived.test6
-rw-r--r--mysql-test/t/func_crypt.test7
-rw-r--r--mysql-test/t/func_str.test2
-rw-r--r--mysql-test/t/multi_update.test6
-rw-r--r--mysql-test/t/outfile.test5
-rw-r--r--mysql-test/t/query_cache.test1
-rw-r--r--mysql-test/t/rpl_temporary.test77
-rw-r--r--mysql-test/t/subselect.test64
-rw-r--r--mysql-test/t/update.test5
-rw-r--r--mysys/Makefile.am5
-rw-r--r--mysys/charset.c210
-rw-r--r--mysys/test_xml.c105
-rw-r--r--mysys/xml.c374
-rw-r--r--sql/field.cc35
-rw-r--r--sql/field.h6
-rw-r--r--sql/filesort.cc2
-rw-r--r--sql/gstream.cc38
-rw-r--r--sql/item.cc236
-rw-r--r--sql/item.h243
-rw-r--r--sql/item_cmpfunc.cc124
-rw-r--r--sql/item_cmpfunc.h53
-rw-r--r--sql/item_func.cc19
-rw-r--r--sql/item_func.h9
-rw-r--r--sql/item_row.cc44
-rw-r--r--sql/item_row.h22
-rw-r--r--sql/item_strfunc.cc65
-rw-r--r--sql/item_strfunc.h32
-rw-r--r--sql/item_subselect.cc405
-rw-r--r--sql/item_subselect.h79
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/log_event.h6
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/nt_servc.cc32
-rw-r--r--sql/opt_range.cc11
-rw-r--r--sql/password.c2
-rw-r--r--sql/protocol.cc63
-rw-r--r--sql/set_var.cc6
-rw-r--r--sql/share/Makefile.am4
-rw-r--r--sql/share/charsets/Index70
-rw-r--r--sql/share/charsets/Index.xml455
-rw-r--r--sql/share/czech/errmsg.txt1
-rw-r--r--sql/share/danish/errmsg.txt1
-rw-r--r--sql/share/dutch/errmsg.txt1
-rw-r--r--sql/share/english/errmsg.txt1
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt1
-rw-r--r--sql/share/german/errmsg.txt1
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt1
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt1
-rw-r--r--sql/share/norwegian/errmsg.txt1
-rw-r--r--sql/share/polish/errmsg.txt1
-rw-r--r--sql/share/portuguese/errmsg.txt1
-rw-r--r--sql/share/romanian/errmsg.txt1
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt1
-rw-r--r--sql/share/slovak/errmsg.txt1
-rw-r--r--sql/share/spanish/errmsg.txt1
-rw-r--r--sql/share/swedish/errmsg.txt1
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/spatial.cc6
-rw-r--r--sql/sql_base.cc24
-rw-r--r--sql/sql_cache.cc2
-rw-r--r--sql/sql_class.cc37
-rw-r--r--sql/sql_class.h15
-rw-r--r--sql/sql_derived.cc18
-rw-r--r--sql/sql_help.cc14
-rw-r--r--sql/sql_lex.cc7
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_olap.cc12
-rw-r--r--sql/sql_parse.cc67
-rw-r--r--sql/sql_prepare.cc34
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_show.cc23
-rw-r--r--sql/sql_string.cc2
-rw-r--r--sql/sql_table.cc125
-rw-r--r--sql/sql_test.cc3
-rw-r--r--sql/sql_udf.cc27
-rw-r--r--sql/sql_union.cc7
-rw-r--r--sql/sql_yacc.yy53
-rw-r--r--sql/stacktrace.c6
-rw-r--r--strings/ctype-big5.c1
-rw-r--r--strings/ctype-bin.c1
-rw-r--r--strings/ctype-czech.c1
-rw-r--r--strings/ctype-euc_kr.c1
-rw-r--r--strings/ctype-gb2312.c1
-rw-r--r--strings/ctype-gbk.c1
-rw-r--r--strings/ctype-latin1_de.c1
-rw-r--r--strings/ctype-mb.c2
-rw-r--r--strings/ctype-sjis.c1
-rw-r--r--strings/ctype-tis620.c1
-rw-r--r--strings/ctype-ujis.c1
-rw-r--r--strings/ctype-utf8.c2
-rw-r--r--strings/ctype-win1250ch.c1
-rw-r--r--strings/ctype.c24
-rw-r--r--tests/client_test.c1936
123 files changed, 6000 insertions, 1231 deletions
diff --git a/.bzrignore b/.bzrignore
index 2c115322cc5..379f5401021 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -580,3 +580,4 @@ vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
libmysqld/protocol.cc
+test_xml
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index ad0fa4a4a36..e3da1e2292e 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -70,6 +70,7 @@ ram@mysql.r18.ru
ram@ram.(none)
ranger@regul.home.lan
root@x3.internalnet
+salle@banica.(none)
salle@geopard.(none)
salle@geopard.online.bg
sasha@mysql.sashanet.com
diff --git a/Docs/gis.txt b/Docs/gis.txt
new file mode 100644
index 00000000000..d80a200d5a6
--- /dev/null
+++ b/Docs/gis.txt
@@ -0,0 +1,861 @@
+
+ OpenGIS <http://www.opengis.org> support in MySQL
+
+------------------------------------------------------------------------
+Note: Blue colored lines among the text is features not implemented yet.
+They are:
+
+ * Spatial Reference Systems and their IDs (SRIDs) related things:
+ o Functions like Length() and Area() assume planar coordinate
+ system.
+ o All objects are currently considered to be in the same
+ planar coordinate system.
+ * Function Length() on LineString and MultiLineString currently
+ should be called as GLength().
+* No binary constructors like GeomFromWKB().
+
+We also have to add "PostGIS compatibility" sections.
+
+
+ 1 Introduction
+
+MySQL implements a subset of *SQL2 with Geometry Types* environment
+proposed by OpenGIS consortium's *Simple Features Specification For
+SQL*. In this environment a geometry-valued column is implemented as a
+column whose SQL type is drawn from the set of Geometry Types. SQL
+server supports both textual and binary access to geometry.
+
+
+ 2 OpenGIS Geometry Model in MySQL
+
+MySQL supports the Open GIS Geometry Model based hierarcy of spatial
+objects classes, which consists of:
+
+ * Geometry
+ o *Point*
+ o Curve
+ + *LineString*
+ o Surface
+ + *Polygon*
+ o *GeometryCollection*
+ + *MultiPoint*
+ + MultiCurve
+ # *MultiLineString*
+ + MultiSurface
+ # *MultiPolygon*
+
+The base *Geometry* class has subclasses for Point, Curve, Surface and
+GeometryCollection.
+
+Geometry, Curve, Surface, MultiCurve and MultiSurface are defined to be
+non-instantiable classes, it is not possible to create an object of
+these classes.
+
+Point, LineString, Polygon, GeometryCollection, MultiPoint,
+MultiLineString, MultiPolygon are instantiable classes (bolded on the
+hierarcy tree). MySQL provides a number of functions to construct
+instances of these classes.
+
+TODO: Each spatial object is associated with a Spatial Reference System,
+which describes the coordinate space in which the geometric object is
+defined.
+
+
+ 2.1 Geometry
+
+Geometry is the root class of the hierarchy. Geometry is an abstract
+(non-instantiable) class. The instantiable subclasses of Geometry
+defined in this specification are restricted to 0, 1 and two-dimensional
+geometric objects that exist in two-dimensional coordinate space. All
+instantiable geometry classes are defined so that valid instances of a
+geometry class are topologically closed (i.e. all defined geometries
+include their boundary).
+
+
+ 2.2 Point
+
+A *Point* is a 0-dimensional geometry and represents a single location
+in coordinate space. A Point in the case of 2D has a x-coordinate value
+and a y-coordinate value. In the case of more dimensions, a Point has a
+coordinate value for each dimension. The boundary of a Point is the
+empty set.
+
+
+ 2.3 Curve
+
+A *Curve* is a one-dimensional geometric object usually stored as a
+sequence of points, with the subclass of Curve specifying the form of
+the interpolation between points. MySQL implementation defines only one
+subclass of Curve, LineString, which uses linear interpolation between
+points.
+
+A Curve is simple if it does not pass through the same point twice. A
+Curve is closed if its start point is equal to its end point. The
+boundary of a closed Curve is empty. A Curve that is simple and closed
+is a Ring. The boundary of a non-closed Curve consists of its two end
+points. A Curve is defined as topologically closed.
+
+
+ 2.4 LineString, Line, LinearRing
+
+A LineString is a Curve with linear interpolation between points. Each
+consecutive pair of points defines a line segment. A Line is a
+LineString with exactly 2 points. A LinearRing is a LineString that is
+both closed and simple.
+
+
+ 2.5 Surface
+
+A *Surface* is a two-dimensional geometric object. The OpenGIS Abstract
+Specification defines a simple Surface as consisting of a single 'patch'
+that is associated with one 'exterior boundary' and 0 or more 'interior'
+boundaries. Simple surfaces in three-dimensional space are isomorphic to
+planar surfaces. Polyhedral surfaces are formed by 'stitching' together
+simple surfaces along their boundaries, polyhedral surfaces in
+three-dimensional space may not be planar as a whole.
+
+The boundary of a simple Surface is the set of closed curves
+corresponding to its exterior and interior boundaries.
+
+The only instantiable subclass of Surface defined in this specification,
+Polygon, is a simple Surface that is planar.
+
+
+ 2.6 Polygon
+
+A Polygon is a planar Surface, defined by 1 exterior boundary and 0 or
+more interior boundaries. Each interior boundary defines a hole in the
+Polygon. The assertions for polygons (the rules that define valid
+polygons) are:
+
+ * Polygons are topologically closed.
+ * The boundary of a Polygon consists of a set of LinearRings (i.e.
+ LineStrings which are both simple and closed) that make up its
+ exterior and interior boundaries.
+ * No two rings in the boundary cross, the rings in the boundary of a
+ Polygon may intersect at a Point but only as a tangent.
+ * A Polygon may not have cut lines, spikes or punctures.
+ * The Interior of every Polygon is a connected point set.
+ * The Exterior of a Polygon with 1 or more holes is not connected.
+Each hole defines a connected component of the Exterior.
+
+In the above assertions, Interior, Closure and Exterior have the
+standard topological definitions. The combination of 1 and 3 make a
+Polygon a Regular Closed point set. Polygons are simple geometries.
+
+
+ 2.6 GeometryCollection
+
+A *GeometryCollection* is a geometry that is a collection of 1 or more
+geometries of any class. All the elements in a GeometryCollection must
+be in the same Spatial Reference (i.e. in the same coordinate system).
+GeometryCollection places no other constraints on its elements. However
+subclasses of GeometryCollection described below may restrict membership
+based on dimension and may also place other constraints on the degree of
+spatial overlap between elements.
+
+
+ 2.7 MultiPoint
+
+A *MultiPoint* is a 0 dimensional geometric collection. The elements of
+a MultiPoint are restricted to Points. The points are not connected or
+ordered. A MultiPoint is simple if no two Points in the MultiPoint are
+equal (have identical coordinate values). The boundary of a MultiPoint
+is the empty set.
+
+
+ 2.8 MultiCurve
+
+A MultiCurve is a one-dimensional geometry collection whose elements are
+Curves. MultiCurve is a non-instantiable class, it defines a set of
+methods for its subclasses and is included for reasons of extensibility.
+
+A MultiCurve is simple if and only if all of its elements are simple,
+the only intersections between any two elements occur at points that are
+on the boundaries of both elements.
+
+The boundary of a MultiCurve is obtained by applying the "mod 2 union
+rule": A point is in the boundary of a MultiCurve if it is in the
+boundaries of an odd number of elements of the MultiCurve.
+
+A MultiCurve is closed if all of its elements are closed. The boundary
+of a closed MultiCurve is always empty. A MultiCurve is defined as
+topologically closed.
+
+
+ 2.9 MultiLineString
+
+A *MultiLineString* is a MultiCurve whose elements are LineStrings.
+
+
+ 2.10 MultiSurface
+
+A MultiSurface is a two-dimensional geometric collection whose elements
+are surfaces. The interiors of any two surfaces in a MultiSurface may
+not intersect. The boundaries of any two elements in a MultiSurface may
+intersect at most at a finite number of points.
+
+MultiSurface is a non-instantiable class in this specification, it
+defines a set of methods for its subclasses and is included for reasons
+of extensibility. The instantiable subclass of MultiSurface is
+MultiPolygon, corresponding to a collection of Polygons.
+
+
+ 2.11 MultiPolygon
+
+A MultiPolygon is a MultiSurface whose elements are Polygons.
+
+The assertions for MultiPolygons are :
+
+ * The interiors of 2 Polygons that are elements of a MultiPolygon
+ may not intersect.
+ * The Boundaries of any 2 Polygons that are elements of a
+ MultiPolygon may not cross and may touch at only a finite number
+ of points. (Note that crossing is prevented by assertion 1 above).
+ * A MultiPolygon is defined as topologically closed.
+ * A MultiPolygon may not have cut lines, spikes or punctures, a
+ MultiPolygon is a Regular, Closed point set.
+ * The interior of a MultiPolygon with more than 1 Polygon is not
+ connected, the number of connected components of the interior of a
+MultiPolygon is equal to the number of Polygons in the MultiPolygon.
+
+The boundary of a MultiPolygon is a set of closed curves (LineStrings)
+corresponding to the boundaries of its element Polygons. Each Curve in
+the boundary of the MultiPolygon is in the boundary of exactly 1 element
+Polygon, and every Curve in the boundary of an element Polygon is in the
+boundary of the MultiPolygon.
+
+
+ 3 Exchange of spatial data
+
+MySQL provides binary and textual mechanismes to exchange spatial data.
+Exchange is provided via so called Well Known Binary (WKB) and Well
+Known Textual (WKT) representations of spatial data proposed by OpenGIS
+specifications.
+
+
+ 3.1 Well-known Text representation (WKT)
+
+The Well-known Text (WKT) representation of Geometry is designed to
+exchange geometry data in textual format.
+
+WKT is defined below in Bechus-Naur forms:
+
+ * the notation {}* denotes 0 or more repetitions of the tokens
+ within the braces;
+* the braces do not appear in the output token list.
+
+The text representation of the implemented instantiable geometric types
+conforms to this grammar:
+
+<Geometry Tagged Text> :=
+ <Point Tagged Text>
+ | <LineString Tagged Text>
+ | <Polygon Tagged Text>
+ | <MultiPoint Tagged Text>
+ | <MultiLineString Tagged Text>
+ | <MultiPolygon Tagged Text>
+ | <GeometryCollection Tagged Text>
+
+<Point Tagged Text> :=
+
+ POINT <Point Text>
+
+<LineString Tagged Text> :=
+
+ LINESTRING <LineString Text>
+
+<Polygon Tagged Text> :=
+
+ POLYGON <Polygon Text>
+
+<MultiPoint Tagged Text> :=
+
+ MULTIPOINT <Multipoint Text>
+
+<MultiLineString Tagged Text> :=
+
+ MULTILINESTRING <MultiLineString Text>
+
+<MultiPolygon Tagged Text> :=
+
+ MULTIPOLYGON <MultiPolygon Text>
+
+<GeometryCollection Tagged Text> :=
+
+ GEOMETRYCOLLECTION <GeometryCollection Text>
+
+<Point Text> := EMPTY | ( <Point> )
+
+<Point> := <x> <y>
+
+<x> := double precision literal
+
+<y> := double precision literal
+
+<LineString Text> := EMPTY
+
+ | ( <Point > {, <Point > }* )
+
+<Polygon Text> := EMPTY
+
+ | ( <LineString Text > {, < LineString Text > }*)
+
+<Multipoint Text> := EMPTY
+
+ | ( <Point Text > {, <Point Text > }* )
+
+<MultiLineString Text> := EMPTY
+
+ | ( <LineString Text > {, < LineString Text > }* )
+
+<MultiPolygon Text> := EMPTY
+
+ | ( < Polygon Text > {, < Polygon Text > }* )
+
+<GeometryCollection Text> := EMPTY
+
+ | ( <Geometry Tagged Text> {, <Geometry Tagged Text> }* )
+
+
+ WKT examples
+
+Examples of textual representations of Geometry objects are shown below:
+
+ * |POINT(10 10)| - a Point
+ * |LINESTRING( 10 10, 20 20, 30 40)| - a LineString with three points
+ * |POLYGON((10 10, 10 20, 20 20,20 15, 10 10))| - a Polygon with one
+ exterior ring and 0 interior rings
+ * |MULTIPOINT(10 10, 20 20)| - a MultiPoint with two Points
+ * |MULTILINESTRING((10 10, 20 20), (15 15, 30 15))| - a
+ MultiLineString with two LineStrings
+ * |MULTIPOLYGON(((10 10, 10 20, 20 20, 20 15, 10 10)), ((60 60, 70
+ 70, 80 60, 60 60 ) ))| - a MultiPolygon with two Polygons
+ * |GEOMETRYCOLLECTION( POINT (10 10),POINT (30 30), LINESTRING (15
+ 15, 20 20))| - a GeometryCollection consisting of two Points and
+one LineString
+
+
+ 3.2 Well-known Binary representation (WKB)
+
+Well Known Binary Representations is proposed by OpenGIS specifications
+to exchange geometry data in binary format. This is WKB description:
+
+// Basic Type definitions
+// byte : 1 byte
+// uint32 : 32 bit unsigned integer (4 bytes)
+// double : double precision number (8 bytes)
+// Building Blocks : Point, LinearRing
+
+Point {
+ double [numDimentions];
+};
+
+LinearRing {
+ uint32 numPoints;
+ Point points[numPoints];
+}
+
+enum wkbGeometryType {
+ wkbPoint = 1,
+ wkbLineString = 2,
+ wkbPolygon = 3,
+ wkbMultiPoint = 4,
+ wkbMultiLineString = 5,
+ wkbMultiPolygon = 6,
+ wkbGeometryCollection = 7
+};
+
+enum wkbByteOrder {
+ wkbXDR = 0, // Big Endian
+ wkbNDR = 1 // Little Endian
+};
+
+WKBPoint {
+ byte byteOrder;
+ uint32 wkbType; // 1
+ Point point;
+}
+
+WKBLineString {
+ byte byteOrder;
+ uint32 wkbType; // 2
+ uint32 numPoints;
+ Point points[numPoints];
+}
+
+WKBPolygon {
+ byte byteOrder;
+ uint32 wkbType; // 3
+ uint32 numRings;
+ LinearRing rings[numRings];
+}
+
+WKBMultiPoint {
+ byte byteOrder;
+ uint32 wkbType; // 4
+ uint32 num_wkbPoints;
+ WKBPoint WKBPoints[num_wkbPoints];
+}
+
+WKBMultiLineString {
+ byte byteOrder;
+ uint32 wkbType; // 5
+ uint32 num_wkbLineStrings;
+ WKBLineString WKBLineStrings[num_wkbLineStrings];
+}
+
+wkbMultiPolygon {
+ byte byteOrder;
+ uint32 wkbType; // 6
+ uint32 num_wkbPolygons;
+ WKBPolygon wkbPolygons[num_wkbPolygons];
+}
+
+WKBGeometry {
+ union {
+ WKBPoint point;
+ WKBLineString linestring;
+ WKBPolygon polygon;
+ WKBGeometryCollection collection;
+ WKBMultiPoint mpoint;
+ WKBMultiLineString mlinestring;
+ WKBMultiPolygon mpolygon;
+ }
+
+};
+
+WKBGeometryCollection {
+ byte byte_order;
+ uint32 wkbType; // 7
+ uint32 num_wkbGeometries;
+ WKBGeometry wkbGeometries[num_wkbGeometries];
+}
+
+
+ 3.3 MySQL data types for spatial objects
+
+MySQL implementation of OpenGIS provides the *GEOMETRY* data type to be
+used in CREATE TABLE statements. For example, this statement creates a
+table *geom* with spatial field *g*:
+
+CREATE TABLE geom (
+ g Geometry;
+);
+
+A field of *GEOMETRY* type can store a spatial objects of any OpenGIS
+geometry class described above.
+
+
+ 3.4 Internal spatial data representation
+
+Internally (in *.MYD* files) spatial objects are stored in *WKB*,
+combined with object's *SRID* (a numeric ID of Spatial Reference System
+object associated with). During spatial analysis, for example,
+calculating the fact that one object crosses another one, only those
+with the same *SRID* are accepted.
+
+*SRID* may affect a way in which various spatial characteristics are
+calculated. For example, in different coordinate systems distance
+between two objects may differ even objects have the same coordinates,
+like distance on plane coordinate system and distance on geocentric
+(coordinates on Earth surface) systems are different things.
+
+There is a plan to provide a number of commonly used coordinate systems
+in MySQL OpenGIS implementation.
+
+
+ 3.5 INSERTing spatial objects
+
+Spatial data can be INSERTed using a spatial constructor. The term
+*spatial constructor* is used in this manual to refer to any function
+which can construct a value of GEOMETRY type, i.e. an internal MySQL
+representation of spatial data.
+
+
+ 3.5.1 Textual spatial constructors
+
+Textual spatial constructors take a gemometry description in WKT and
+built GEOMETRY value.
+
+ * |*GeomFromText(geometryTaggedText String [, SRID
+ Integer]):Geometry *| - constructs a Geometry value from its
+ well-known textual representation.
+
+ |*GeomFromText()*| function accepts a WKT of any Geometry class as
+ it's first argument.
+
+ For construction of Geometry values restricted to a particular
+ subclass, an implementation also provides a class-specific
+ construction function for each instantiable subtype as described
+ in the list below:
+
+ * |*PointFromText(pointTaggedText String [,SRID Integer]):Point *| -
+ constructs a Point
+
+ * |*LineFromText(lineStringTaggedText String [,SRID
+ Integer]):LineString *| - constructs a LineString
+
+ * |*PolyFromText(polygonTaggedText String [,SRID Integer]):Polygon
+ *|- constructs a Polygon
+
+ * |*MPointFromText(multiPointTaggedText String [,SRID
+ Integer]):MultiPoint *| - constructs a MultiPoint
+
+ * |*MLineFromText(multiLineStringTaggedText String [,SRID
+ Integer]):MultiLineString *| - constructs a MultiLineString
+
+ * |*MPolyFromText(multiPolygonTaggedText String [,SRID
+ Integer]):MultiPolygon *| - constructs a MultiPolygon
+
+ * |*GeomCollFromText(geometryCollectionTaggedText String [,SRID
+ Integer]):GeomCollection *| - constructs a GeometryCollection
+
+Usage examples:
+
+INSERT INTO geom VALUES (GeomFromText('POINT(1 1)'))
+INSERT INTO geom VALUES (GeomFromText('LINESTRING(0 0,1 1,2 2)'))
+INSERT INTO geom VALUES (GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,7 5,7 7,5 7, 5 5))'))
+INSERT INTO geom VALUES (GeomFromText('GEOMETRYCOLLECTION(POINT(1 1),LINESTRING(0 0,1 1,2 2,3 3,4 4))'))
+
+The second argument of spatial constructirs, described above, is
+currently ignored, It will be used to specify SRID in the future.
+Nowdays, it is added for reasons of compatibility with OpenGIS
+specifications and PostGIS implementation.
+
+As an optional feature, an implementation may also support building of
+Polygon or MultiPolygon values given an arbitrary collection of possibly
+intersecting rings or closed LineString values. Implementations that
+support this feature should include the following functions:
+
+ * |*BdPolyFromText(multiLineStringTaggedText String, SRID
+ Integer):Polygon *| - constructs a Polygon given an arbitrary
+ collection of closed linestrings as a MultiLineString text
+ representation.
+ * |*BdMPolyFromText(multiLineStringTaggedText String, SRID
+ Integer):MultiPolygon *| - constructs a MultiPolygon given an
+ arbitrary collection of closed linestrings as a MultiLineString
+text representation.
+
+
+ 3.5.2 Binary spatial constructors
+
+ * |*GeomFromWKB(WKBGeometry Binary, SRID Integer):Geometry *| -
+ constructs a Geometry value given its well-known binary
+ representation.
+
+ |*GeomFromWKB()*| function can accept in it's first argument a WKB
+ of Geometry of any class. For construction of Geometry values
+ restricted to a particular subclass, an implementation also
+ provides a class-specific construction function for each
+ instantiable subclass as described in the list below:
+
+ * |*PointFromWKB(WKBPoint Binary, SRID Integer):Point - *|constructs
+ a Point
+ * |* LineFromWKB(WKBLineString Binary, SRID Integer):LineString *| -
+ constructs a LineString
+ * |* PolyFromWKB(WKBPolygon Binary, SRID Integer):Polygon *| -
+ constructs a Polygon
+ * |* MPointFromWKB(WKBMultiPoint Binary, SRID Integer):MultiPoint *|
+ - constructs a MultiPoint
+ * |* MLineFromWKB(WKBMultiLineString Binary, SRID
+ Integer):MultiLineString *| - constructs a MultiLineString
+ * |* MPolyFromWKB(WKBMultiPolygon Binary, SRID Integer):
+ MultiPolygon *| - constructs a MultiPolygon
+ * |* GeomCollFromWKB(WKBGeometryCollection Binary, SRID Integer):
+GeomCollection *| - constructs a GeometryCollection
+
+As an optional feature, an implementation may also support the uilding'
+of Polygon or MultiPolygon values given an arbitrary collection of
+possibly intersecting rings or closed LineString values. Implementations
+that support this feature should include the following functions:
+
+ * |* BdPolyFromWKB (WKBMultiLineString Binary,SRID Integer): Polygon
+ *| - constructs a Polygon given an arbitrary collection of closed
+ linestrings as a MultiLineString binary representation.
+ * |*BdMPolyFromWKB(WKBMultiLineString Binary, SRID
+ Integer):MultiPolygon *| - constructs a MultiPolygon given an
+ arbitrary collection of closed linestrings as a MultiLineString
+binary representation.
+
+Inserting in *WKB* assumes that |GeomFromWKB()| function argument
+contains a buffer with a correctly formed spatial object in WKB. In ODBC
+applications it can be done using binding of argument. One also can
+insert object in *WKB* using |mysql_escape_string()| in |libmysqlclient|
+applications.
+
+For example:
+
+INSERT INTO geom VALUES (GeomFromWKB(buf,SRID));
+
+where |buf| is a binary buffer with a spatial object in *WKB*
+representation.
+
+
+ 3.5 SELECTing spatial objects
+
+Spatial objects are selected either in *WKT* or *WKB* representation by
+use of AsText() and AsBinary() functions correspondently.
+
+
+mysql> select AsText(g) as g from geom;
++-------------------------+
+| g |
++-------------------------+
+| POINT(1 1) |
+| LINESTRING(0 0,1 1,2 2) |
++-------------------------+
+2 rows in set (0.00 sec)
+
+mysql>
+
+The query:
+
+SELECT AsBinary(g) FROM geom
+
+returns a BLOB which contains *WKB* representation of object.
+
+
+ 4 Functions for spatial analysis
+
+
+ 4.1 Basic functions on Geometry
+
+ * |*AsText(g:Geometry):String*| - Exports this Geometry to a
+ specific well-known text representation of Geometry.
+ * |*AsBinary(g:Geometry):Binary*| - Exports this Geometry to a
+ specific well-known binary representation of Geometry.
+ * |*GeometryType(g:Geometry):String*| - Returns the name of the
+ instantiable subtype of Geometry of which this Geometry instance
+ is a member. The name of the instantiable subtype of Geometry is
+ returned as a string.
+ * |*Dimension(g:Geometry):Integer*| - The inherent dimension of this
+ Geometry object, which must be less than or equal to the
+ coordinate dimension. This specification is restricted to
+ geometries in two-dimensional coordinate space.
+ * |*IsEmpty(g:Geometry):Integer*| - Returns 1 (TRUE) if this
+ Geometry is the empty geometry . If true, then this Geometry
+ represents the empty point set, , for the coordinate space.
+ * |*IsSimple(g:Geometry):Integer *| - Returns 1 (TRUE) if this
+ Geometry has no anomalous geometric points, such as self
+ intersection or self tangency. The description of each
+ instantiable geometric class includes the specific conditions that
+ cause an instance of that class to be classified as not simple.
+ * |*SRID(g:Geometry):Integer*| - Returns the Spatial Reference
+ System ID for this Geometry.
+ * |*Distance(g1:Geometry,g2:Geometry):Double*| - the shortest
+distance between any two points in the two geometries.
+
+
+ 4.2 Functions for specific geometry type
+
+
+ GeometryCollection functions
+
+ * *NumGeometries(g:GeometryCollection ):Integer * -Returns the
+ number of geometries in this GeometryCollection.
+ * *GeometryN(g:GeometryCollection,N:integer):Geometry * -Returns the
+Nth geometry in this GeometryCollection.
+
+
+ Point functions
+
+ * *X(p:Point):Double* -The x-coordinate value for this Point.
+* *Y(p:Point):Double* -The y-coordinate value for this Point.
+
+
+ LineString functions
+
+ * *StartPoint(l:LineString):Point* The start point of this LineString.
+ * *EndPoint(l:LineString):Point* The end point of this LineString.
+ * *PointN(l:LineString,N:Integer):Point* Returns the specified point
+ N in this Linestring.
+ * *Length(l:LineString):Double* The length of this LineString in its
+ associated spatial reference.
+ * *IsRing(l:LineString):Integer* Returns 1 (TRUE) if this LineString
+ is closed (StartPoint ( ) = EndPoint ( )) and this LineString is
+ simple (does not pass through the same point more than once).
+ * *IsClosed(l:LineString):Integer* Returns 1 (TRUE) if this
+ LineString is closed (StartPoint ( ) = EndPoint ( )).
+ * *NumPoints(l:LineString):Integer* The number of points in this
+LineString.
+
+
+ MultiLineString functions
+
+ * *Length(m:MultiLineString):Double* The Length of this
+ MultiLineString which is equal to the sum of the lengths of the
+ elements.
+ * *IsClosed(m:MultiLineString):Integer* Returns 1 (TRUE) if this
+ MultiLineString is closed (StartPoint() = EndPoint() for each
+LineString in this MultiLineString)
+
+
+ Polygon functions
+
+ * *Area(p:Polygon):Double* The area of this Polygon, as measured in
+ the spatial reference system of this Polygon.
+ * *Centroid(p:Polygon):Point* The mathematical centroid for this
+ Polygon as a Point. The result is not guaranteed to be on this
+ Polygon.
+ * *PointOnSurface(p:Polygon):Point* A point guaranteed to be on this
+ Polygon.
+ * *NumInteriorRing(p:Polygon):Integer* Returns the number of
+ interior rings in this Polygon.
+ * *ExteriorRing(p:Polygon):LineString* Returns the exterior ring of
+ this Polygon as a LineString.
+ * *InteriorRingN(p:Polygon,N:Integer):LineString* Returns the Nth
+interior ring for this Polygon as a LineString.
+
+
+ MultiPolygon functions
+
+ * *Area(m:MultuSurface):Double* The area of this MultiPolygon, as
+ measured in the spatial reference system of this MultiPolygon.
+ * *Centroid(m:MultyPolygon):Point* The mathematical centroid for
+ this MultiPolygon as a Point. The result is not guaranteed to be
+ on this MultiPolygon.
+ * *PointOnSurface(m:MultuPolygon):Point* A Point guaranteed to be on
+this MultiPolygon.
+
+Notes: /functions for specific geometry type retrun NULL if passed
+object type is incorrect. For example Area() returns NULL if object type
+is neither Polygon nor MultiPolygon/
+
+
+ 4.3 Spatial operations (compound spatial constructors)
+
+ * |*Envelope(g:Geometry):Geometry*|The minimum bounding box for this
+ Geometry, returned as a Geometry. The polygon is defined by the
+ corner points of the bounding box
+ |POLYGON((MINX,MINY),(MAXX,MINY),(MAXX,MAXY),(MINX,MAXY),(MINX,MINY))|.
+
+ * |*Boundary(g:Geometry):Geometry*| - returns the closure of the
+ combinatorial boundary of this Geometry.
+ * |*Intersection(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set intersection of g1 with g2.
+ * |*Union(g1,g2:Geometry):Geometry*| - a geometry that represents
+ the point set union of g1 with g2.
+ * |*Difference(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set difference of g1 with g2.
+ * |*SymDifference(g1,g2:Geometry):Geometry*| - a geometry that
+ represents the point set symmetric difference of g1 with g2.
+ * |*Buffer(g:Geometry,distance:Double):Geometry*| - a geometry that
+ represents all points whose distance from g is less than or equal
+ to distance.
+ * |*ConvexHull(g:Geometry):Geometry*| - a geometry that represents
+the convex hull of g.
+
+
+ 4.4 Functions for testing Spatial Relations between geometric objects
+
+ * |*Equals(g1,g2)*| - Returns 1 if g1 is spatially equal to g2.
+ * |*Disjoint(g1,g2)*| - Returns 1 if g1 is spatially disjoint from g2.
+ * |*Intersects(g1,g2)*| - Returns 1 if g1 spatially intersects g2.
+ * |*Touches(g1,g2)*| - Returns 1 if g1 spatially touches g2.
+ * |*Crosses(g1,g2)*| - Returns 1 if g1 spatially crosses g2.
+ * |*Within(g1,g2)*| - Returns 1 if g1 is spatially within g2.
+ * |*Contains(g1,g2)*| - Returns 1 if g1 spatially contains g2.
+* |*Overlaps(g1,g2)*| - Returns 1 if g1 spatially overlaps g2.
+
+
+ 5 Optimizing spatial analysis
+
+
+ 5.1 MBR
+
+MBR is a minimal bounding rectangle (box) for spatial object. It can be
+represented as a set of min and max values of each dimension.
+
+For example:
+
+(Xmin,Xmax,Ymin,Ymax)
+
+
+ 5.2 Using SPATIAL indexes
+
+To optimize spatial object relationships analysis it is possible to
+create a spatial index on geometry field using R-tree algorythm. R-tree
+based spatial indexes store MBRs of spatial objects as a key values.
+
+CREATE SPATIAL INDEX gind ON geom (g);
+
+Or together with table definition:
+
+CREATE TABLE geom (
+ g GEOMETRY,
+ SPATIAL INDEX(g)
+);
+
+Optimizer attaches R-tree based SPATIAL index when a query with spatial
+objects relationship functions is executed in WHERE clause.
+
+For example:
+
+SELECT geom.name FROM geom
+ WHERE Within(geom.g,GeomFromText('POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))',SRID));
+
+
+ 8 OpenGIS extensions implemented in MySQL
+
+MySQL provides it's own constructors to build geometry objects:
+
+ * |*Point(double,double,SRID)*| - constructs a geometry of Point
+ class using it's coordinates and SRID.
+ * |*MultiPoint(Point,Point,...,Point)*| - constructs a MultiPoint
+ using Points. When any argument is not a geometry of Point class
+ the return value is NULL.
+ * |*LineString(Point,Point,...,Point)*| - constructs a LineString
+ from a number of Points. When any argument is not a geometry of
+ Point class the return value is NULL. When the number of Points is
+ less than two the return value is NULL.
+ * |*MultiLineString(LineString,LineString,...,LineString)*| -
+ constructs a MultiLineString using using LineStrings. When any
+ argument is not a geometry of LineStringClass return value is NULL.
+ * |*Polygon(LineString,LineString,...,LineString)*| - constructs a
+ Polygon from a number of LineStrings. When any argument is not a
+ LinearRing (i.e. not closed and simple geometry of class
+ LineString) the return value is NULL.
+ * |*MultiPolygon(Polygon,Polygon,...,Polygon)*| - constructs a
+ MultiPolygon from a set of Polygons. When any argument is not a
+ Polygon, the rerurn value is NULL.
+ * |*GeometryCollection(Geometry,Geometry,..,Geometry)*| - constucts
+ a GeometryCollection. When any argument is not a valid geometry
+object of any instantiable class, the return value is NULL.
+
+The above functions (except Point()) return NULL if arguments are not in
+the same spatial reference system (i.e. have different SRIDs).
+
+
+ Examples:
+
+INSERT INTO geom SELECT Point(x,y,SRID) FROM coords;
+SELECT AsText(g) FROM geom WHERE
+ Contains(Polygon(LineString(Point(0,0),Point(0,1),Point(1,1),Point(1,0),Point(0,0)),SRID),geom.g);
+
+
+ 9 Things that differ in MySQL implemention and OpenGIS specifications
+
+
+ 9.1 Single GEOMETRY type
+
+Besides a GEOMETRY type, OpenGIS consortium specifications suggest the
+implementation of several spatial field types correspondent to every
+instansiable object subclass. For example a *Point* type is proposed to
+restrict data stored in a field of this type to only Point OpenGIS
+subclass. MySQL provides an implementation of single GEOMETRY type which
+doesn't restrict objects to certain OpenGIS subclass.
+
+
+ 9.2 No additional Metadata Views
+
+OpenGIS specifications propose several additional metadata views. For
+example, a system view named GEOMETRY_COLUMNS contains a description of
+geometry columns, one row for each geometry column in the database.
+
+
+ 9.3 No functions to add/drop spatial columns
+
+OpenGIS assumes that columns can be added/dropped using
+AddGeometryColumn() and DropGeometryColumn() functions correspondently.
+In MySQL implementation one should use ALTER TABLE instead.
diff --git a/client/mysql.cc b/client/mysql.cc
index 9ee441a7709..680175f2123 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1414,7 +1414,6 @@ static int com_server_help(String *buffer __attribute__((unused)),
server_cmd= cmd_buf;
}
- char buff[16], time_buf[32];
MYSQL_RES *result;
ulong timer;
uint error= 0;
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 2de4a9b81b5..408a5873589 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -117,7 +117,7 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
- {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"replace", 'r', "If duplicate unique key was found, replace old row.",
(gptr*) &replace, (gptr*) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index df624a02c55..e6e21f177ef 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -179,7 +179,7 @@ static struct my_option my_long_options[] =
{"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
+ {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory)",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_SMEM
{"shared_memory_base_name", OPT_SHARED_MEMORY_BASE_NAME,
diff --git a/include/Makefile.am b/include/Makefile.am
index c88e1ee1e40..652278e8a80 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -16,7 +16,7 @@
# MA 02111-1307, USA
BUILT_SOURCES = mysql_version.h m_ctype.h my_config.h
-pkginclude_HEADERS = dbug.h m_string.h my_sys.h my_list.h \
+pkginclude_HEADERS = dbug.h m_string.h my_sys.h my_list.h my_xml.h \
mysql.h mysql_com.h mysqld_error.h mysql_embed.h \
my_semaphore.h my_pthread.h my_no_pthread.h raid.h \
errmsg.h my_global.h my_net.h my_alloc.h \
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 09a24201588..85397796e73 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -49,6 +49,7 @@ typedef struct unicase_info_st {
#define MY_CS_INDEX 4 /* sets listed in the Index file */
#define MY_CS_LOADED 8 /* sets that are currently loaded */
#define MY_CS_BINSORT 16 /* if binary sort order */
+#define MY_CS_PRIMARY 32 /* if primary collation */
#define MY_CHARSET_UNDEFINED 0
#define MY_CHARSET_CURRENT (default_charset_info->number)
@@ -65,6 +66,7 @@ typedef struct charset_info_st
{
uint number;
uint state;
+ const char *csname;
const char *name;
const char *comment;
uchar *ctype;
@@ -127,6 +129,7 @@ typedef struct charset_info_st
int (*l10tostr)(struct charset_info_st *, char *to, uint n, int radix, long int val);
int (*ll10tostr)(struct charset_info_st *, char *to, uint n, int radix, longlong val);
+ /* String-to-number convertion routines */
long (*strntol)(struct charset_info_st *, const char *s, uint l,char **e, int base);
ulong (*strntoul)(struct charset_info_st *, const char *s, uint l, char **e, int base);
longlong (*strntoll)(struct charset_info_st *, const char *s, uint l, char **e, int base);
diff --git a/include/my_xml.h b/include/my_xml.h
new file mode 100644
index 00000000000..0d968ab38c7
--- /dev/null
+++ b/include/my_xml.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifndef _my_xml_h
+#define _my_xml_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define MY_XML_OK 0
+#define MY_XML_ERROR 1
+
+typedef struct xml_stack_st
+{
+ char errstr[128];
+ char attr[128];
+ char *attrend;
+ const char *beg;
+ const char *cur;
+ const char *end;
+ void *user_data;
+ int (*enter)(struct xml_stack_st *st,const char *val, uint len);
+ int (*value)(struct xml_stack_st *st,const char *val, uint len);
+ int (*leave)(struct xml_stack_st *st,const char *val, uint len);
+} MY_XML_PARSER;
+
+void my_xml_parser_create(MY_XML_PARSER *st);
+void my_xml_parser_free(MY_XML_PARSER *st);
+int my_xml_parse(MY_XML_PARSER *st,const char *str, uint len);
+
+void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, const char *, uint len));
+void my_xml_set_user_data(MY_XML_PARSER *st, void *);
+
+uint my_xml_error_pos(MY_XML_PARSER *st);
+uint my_xml_error_lineno(MY_XML_PARSER *st);
+
+const char *my_xml_error_string(MY_XML_PARSER *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _my_xml_h */
diff --git a/include/mysql.h b/include/mysql.h
index f9b8c1ecbb3..a2b48c0c43d 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -509,7 +509,7 @@ MYSQL_RES *STDCALL mysql_prepare_result(MYSQL_STMT *stmt);
#define MYSQL_STATUS_ERROR 2
#define MYSQL_NO_DATA 100
#define MYSQL_NEED_DATA 99
-#define MYSQL_LONG_DATA_END 0xFF
+#define MYSQL_NULL_DATA (-1)
#define mysql_reload(mysql) mysql_refresh((mysql),REFRESH_GRANT)
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 81a24e89164..377f714bfff 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -265,4 +265,5 @@
#define ER_DERIVED_MUST_HAVE_ALIAS 1246
#define ER_SELECT_REDUCED 1247
#define ER_TABLENAME_NOT_ALLOWED_HERE 1248
-#define ER_ERROR_MESSAGES 249
+#define ER_NOT_SUPPORTED_AUTH_MODE 1249
+#define ER_ERROR_MESSAGES 250
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index a2e6fddff0f..4d8b703fb2d 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -58,7 +58,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_loadpath.lo my_pthread.lo my_thr_init.lo \
thr_mutex.lo mulalloc.lo string.lo default.lo \
my_compress.lo array.lo my_once.lo list.lo my_net.lo \
- charset.lo hash.lo mf_iocache.lo \
+ charset.lo xml.lo hash.lo mf_iocache.lo \
mf_iocache2.lo my_seek.lo \
my_pread.lo mf_cache.lo my_vsnprintf.lo md5.lo sha1.lo\
my_getopt.lo my_gethostbyname.lo my_port.lo
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 8cf59281719..bb0059f8e25 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1760,7 +1760,7 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
mysql->options.ssl_ca= strdup_if_not_null(ca);
mysql->options.ssl_capath= strdup_if_not_null(capath);
mysql->options.ssl_cipher= strdup_if_not_null(cipher);
-#endif
+#endif /* HAVE_OPENSSL */
return 0;
}
@@ -1770,10 +1770,10 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
NB! Errors are not reported until you do mysql_real_connect.
**************************************************************************/
+#ifdef HAVE_OPENSSL
static void
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
{
-#ifdef HAVE_OPENSLL
my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
@@ -1787,8 +1787,8 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
mysql->options.ssl_cipher= 0;
mysql->options.use_ssl = FALSE;
mysql->connector_fd = 0;
-#endif /* HAVE_OPENSLL */
}
+#endif /* HAVE_OPENSSL */
/**************************************************************************
Connect to sql server
@@ -3819,12 +3819,13 @@ static my_bool my_realloc_str(NET *net, ulong length)
1 error
*/
-static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
+static my_bool read_prepare_result(MYSQL_STMT *stmt)
{
uchar *pos;
uint field_count;
+ ulong length, param_count;
MYSQL_DATA *fields_data;
- ulong length;
+ MYSQL *mysql= stmt->mysql;
DBUG_ENTER("read_prepare_result");
mysql= mysql->last_used_con;
@@ -3832,9 +3833,9 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
DBUG_RETURN(1);
pos=(uchar*) mysql->net.read_pos;
- stmt->stmt_id= uint4korr(pos); pos+=4;
- field_count= uint2korr(pos); pos+=2;
- stmt->param_count=uint2korr(pos); pos+=2;
+ stmt->stmt_id= uint4korr(pos); pos+=4;
+ field_count= uint2korr(pos); pos+=2;
+ param_count= uint2korr(pos); pos+=2;
if (field_count != 0)
{
@@ -3857,9 +3858,10 @@ static my_bool read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_OUT_OF_MEMORY);
DBUG_RETURN(0);
}
- stmt->bind= (stmt->params + stmt->param_count);
- stmt->field_count= (uint) field_count;
- mysql->status= MYSQL_STATUS_READY;
+ stmt->bind= (stmt->params + stmt->param_count);
+ stmt->field_count= (uint) field_count;
+ stmt->param_count= (ulong) param_count;
+ stmt->mysql->status= MYSQL_STATUS_READY;
DBUG_RETURN(0);
}
@@ -3903,13 +3905,13 @@ mysql_prepare(MYSQL *mysql, const char *query, ulong length)
}
init_alloc_root(&stmt->mem_root,8192,0);
- if (read_prepare_result(mysql, stmt))
+ stmt->mysql= mysql;
+ if (read_prepare_result(stmt))
{
stmt_close(stmt, 1);
DBUG_RETURN(0);
}
stmt->state= MY_ST_PREPARE;
- stmt->mysql= mysql;
mysql->stmts= list_add(mysql->stmts, &stmt->list);
stmt->list.data= stmt;
DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
@@ -3927,11 +3929,15 @@ mysql_prepare_result(MYSQL_STMT *stmt)
{
MYSQL_RES *result;
DBUG_ENTER("mysql_prepare_result");
-
- if (!stmt->fields)
+
+ if (!stmt->field_count || !stmt->fields)
DBUG_RETURN(0);
- result= &stmt->tmp_result;
- bzero((char*) result, sizeof(MYSQL_RES));
+
+ if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
+ sizeof(ulong)*stmt->field_count,
+ MYF(MY_WME | MY_ZEROFILL))))
+ return 0;
+
result->eof=1; /* Marker for buffered */
result->fields= stmt->fields;
result->field_count= stmt->field_count;
@@ -4083,12 +4089,13 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
DBUG_ENTER("store_param");
DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %d", param->buffer_type,
param->buffer ? param->buffer : "0", *param->length));
-
- if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL)
+
+ if (param->is_null || param->buffer_type == MYSQL_TYPE_NULL ||
+ *param->length == MYSQL_NULL_DATA)
store_param_null(net, param);
else
{
- /* Allocate for worst case (long string) */
+ /* Allocate for worst case (long string) */
if ((my_realloc_str(net, 9 + *param->length)))
DBUG_RETURN(1);
(*param->store_param_func)(net, param);
@@ -4096,7 +4103,6 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
DBUG_RETURN(0);
}
-
/*
Send the prepare query to server for execution
*/
@@ -4120,13 +4126,6 @@ static my_bool execute(MYSQL_STMT * stmt, char *packet, ulong length)
}
stmt->state= MY_ST_EXECUTE;
mysql_free_result(stmt->result);
-#if USED_IN_FETCH
- if (stmt->res_buffers) /* Result buffers exists, cache results */
- {
- mysql_free_result(stmt->result);
- stmt->result= mysql_store_result(mysql);
- }
- #endif
DBUG_RETURN(0);
}
@@ -4407,6 +4406,327 @@ mysql_send_long_data(MYSQL_STMT *stmt, uint param_number,
****************************************************************************/
+static ulong get_field_length(uint type)
+{
+ ulong length;
+
+ switch (type) {
+
+ case MYSQL_TYPE_TINY:
+ length= 1;
+ break;
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ length= 2;
+ break;
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_FLOAT:
+ length= 4;
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_DOUBLE:
+ length= 8;
+ break;
+ default:
+ length= 0;
+ }
+ return length;
+}
+
+static void send_data_long(MYSQL_BIND *param, longlong value)
+{
+ char *buffer= param->buffer;
+
+ *param->length= get_field_length(param->buffer_type);
+ switch(param->buffer_type) {
+
+ case MYSQL_TYPE_TINY:
+ *param->buffer= (uchar) value;
+ break;
+ case MYSQL_TYPE_SHORT:
+ int2store(buffer, (short)value);
+ break;
+ case MYSQL_TYPE_LONG:
+ int4store(buffer, (int32)value);
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ int8store(buffer, (longlong)value);
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ {
+ uint length= sprintf(buffer,"%lld",value);
+ *param->length= length;
+ buffer[length]='\0';
+ }
+ }
+}
+
+static void send_data_double(MYSQL_BIND *param, double value)
+{
+ char *buffer= param->buffer;
+
+ *param->length= get_field_length(param->buffer_type);
+ switch(param->buffer_type) {
+
+ case MYSQL_TYPE_TINY:
+ *buffer= (uchar)value;
+ break;
+ case MYSQL_TYPE_SHORT:
+ int2store(buffer, (short)value);
+ break;
+ case MYSQL_TYPE_LONG:
+ int4store(buffer, (int32)value);
+ break;
+ case MYSQL_TYPE_LONGLONG:
+ int8store(buffer, (longlong)value);
+ break;
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data= (float)value;
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data= (double)value;
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ {
+ uint length= sprintf(buffer,"%g",value);
+ *param->length= length;
+ buffer[length]='\0';
+ }
+ }
+}
+
+static void send_data_str(MYSQL_BIND *param, char *value, uint src_length)
+{
+ char *buffer= param->buffer;
+
+ *param->length= get_field_length(param->buffer_type);
+ switch(param->buffer_type) {
+
+ case MYSQL_TYPE_TINY:
+ *buffer= (char)*value;
+ break;
+ case MYSQL_TYPE_SHORT:
+ {
+ short data= (short)sint2korr(value);
+ int2store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_LONG:
+ {
+ int32 data= (int32)sint4korr(value);
+ int4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong data= sint8korr(value);
+ int8store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ {
+ float data;
+ float4get(data, value);
+ float4store(buffer, data);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double data;
+ float8get(data, value);
+ float8store(buffer, data);
+ break;
+ }
+ default:
+ *param->length= src_length;
+ memcpy(buffer, value, src_length);
+ buffer[src_length]='\0';
+ }
+}
+
+static my_bool fetch_results(MYSQL_STMT *stmt, MYSQL_BIND *param,
+ uint field_type, uchar **row)
+{
+ ulong length;
+
+ length= get_field_length(field_type);
+ switch (field_type) {
+
+ case MYSQL_TYPE_TINY:
+ {
+ uchar value= (uchar) **row;
+ send_data_long(param,(longlong)value);
+ break;
+ }
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ {
+ short value= (short)sint2korr(*row);
+ send_data_long(param,(longlong)value);
+ break;
+ }
+ case MYSQL_TYPE_LONG:
+ {
+ int32 value= (int32)sint4korr(*row);
+ send_data_long(param,(int32)value);
+ break;
+ }
+ case MYSQL_TYPE_LONGLONG:
+ {
+ longlong value= (longlong)sint8korr(*row);
+ send_data_long(param,value);
+ break;
+ }
+ case MYSQL_TYPE_FLOAT:
+ {
+ float value;
+ float4get(value,*row);
+ send_data_double(param,(double)value);
+ break;
+ }
+ case MYSQL_TYPE_DOUBLE:
+ {
+ double value;
+ float8get(value,*row);
+ send_data_double(param,(double)value);
+ break;
+ }
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
+ {
+ uchar month,day;
+ short year;
+ int arg_length;
+ char ts[50],frac[10],time[20],date[20];
+
+ if (!(length= net_field_length(row)))
+ {
+ *param->length= 0;
+ break;
+ }
+ if (param->buffer_type < MYSQL_TYPE_VAR_STRING ||
+ param->buffer_type > MYSQL_TYPE_STRING)
+ {
+ /*
+ Don't allow fetching of date/time/ts to non-string types
+ TODO: Allow fetching of date or time to long types.
+ */
+ sprintf(stmt->last_error,
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ param->buffer_type, param->param_number);
+ return 1;
+ }
+
+ arg_length= 0;
+ if (length > 7)
+ {
+ int sec_part= sint4korr(*row+7);
+ sprintf(frac,".%04d", sec_part);
+ arg_length+= 5;
+ }
+ if (length == 7)
+ {
+ uchar hour, minute, sec;
+ hour= *(*row+4);
+ minute= *(*row+5);
+ sec= *(*row+6);
+ sprintf((char *)time," %02d:%02d:%02d",hour,minute,sec);
+ arg_length+= 9;
+ }
+
+ year= sint2korr(*row);
+ month= *(*row+2);
+ day= *(*row+3);
+ sprintf((char*) date,"%04d-%02d-%02d",year,month,day);
+ arg_length+= 10;
+
+ if (arg_length != 19)
+ time[0]='\0';
+ if (arg_length != 24)
+ frac[0]='\0';
+
+ strxmov(ts,date,time,frac,NullS);
+ send_data_str(param,ts,arg_length);
+ break;
+ }
+ case MYSQL_TYPE_TIME:
+ {
+ int day, arg_length;
+ uchar hour, minute, sec;
+ char ts[255], frac[20], time[20];
+ const char *sign= "";
+
+ if (!(length= net_field_length(row)))
+ {
+ *param->length= 0;
+ break;
+ }
+ if (param->buffer_type < MYSQL_TYPE_VAR_STRING ||
+ param->buffer_type > MYSQL_TYPE_STRING)
+ {
+ /*
+ Don't allow fetching of date/time/ts to non-string types
+
+ TODO: Allow fetching of time to long types without
+ any conversion.
+ */
+ sprintf(stmt->last_error,
+ ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
+ param->buffer_type, param->param_number);
+ return 1;
+ }
+ arg_length= 0;
+ if (length > 8)
+ {
+ int sec_part= sint4korr(*row+8);
+ sprintf(frac,".%04d", sec_part);
+ arg_length+= 5;
+ }
+
+ if (**row)
+ sign="-";
+
+ day= sint4korr(*row); /* TODO: how to handle this case */
+ hour= *(*row+5);
+ minute= *(*row+6);
+ sec= *(*row+7);
+ arg_length+= sprintf((char *)time,"%s%02d:%02d:%02d",sign,hour,minute,sec);
+
+ if (arg_length <= 9)
+ frac[0]='\0';
+
+ strxmov(ts,time,frac,NullS);
+ send_data_str(param,ts,arg_length);
+ break;
+ }
+ default:
+ length= net_field_length(row);
+ send_data_str(param,*row,length);
+ break;
+ }
+ *row+= length;
+ return 0;
+}
+
static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
{
*param->buffer= (uchar) **row;
@@ -4415,31 +4735,31 @@ static void fetch_result_tinyint(MYSQL_BIND *param, uchar **row)
static void fetch_result_short(MYSQL_BIND *param, uchar **row)
{
- short value= *(short *)row;
+ short value = (short)sint2korr(*row);
int2store(param->buffer, value);
- *row+=2;
+ *row+= 2;
}
static void fetch_result_int32(MYSQL_BIND *param, uchar **row)
{
- int32 value= *(int32 *)row;
+ int32 value= (int32)sint4korr(*row);
int4store(param->buffer, value);
- *row+=4;
+ *row+= 4;
}
static void fetch_result_int64(MYSQL_BIND *param, uchar **row)
-{
- longlong value= *(longlong *)row;
+{
+ longlong value= (longlong)sint8korr(*row);
int8store(param->buffer, value);
- *row+=8;
+ *row+= 8;
}
static void fetch_result_float(MYSQL_BIND *param, uchar **row)
{
float value;
float4get(value,*row);
- float4store(param->buffer, *row);
- *row+=4;
+ float4store(param->buffer, value);
+ *row+= 4;
}
static void fetch_result_double(MYSQL_BIND *param, uchar **row)
@@ -4447,15 +4767,16 @@ static void fetch_result_double(MYSQL_BIND *param, uchar **row)
double value;
float8get(value,*row);
float8store(param->buffer, value);
- *row+=8;
+ *row+= 8;
}
static void fetch_result_str(MYSQL_BIND *param, uchar **row)
{
ulong length= net_field_length(row);
memcpy(param->buffer, (char *)*row, length);
+ *(param->buffer+length)= '\0';
*param->length= length;
- *row+=length;
+ *row+= length;
}
/*
@@ -4511,9 +4832,10 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
- param->length= &param->buffer_length;
+ param->bind_length= 0;
param->fetch_result= fetch_result_str;
break;
default:
@@ -4532,41 +4854,51 @@ my_bool STDCALL mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
Fetch row data to bind buffers
*/
-static my_bool
-stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
+static void
+stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
{
MYSQL_BIND *bind, *end;
- uchar *null_ptr= (uchar*) *row, bit;
-
- row+= (stmt->field_count+9)/8;
- bit= 4; /* First 2 bits are reserved */
-
+ MYSQL_FIELD *field, *field_end;
+ uchar *null_ptr, bit;
+
+ null_ptr= row;
+ row+= (stmt->field_count+9)/8; /* skip null bits */
+ bit= 4; /* first 2 bits are reserved */
+
/* Copy complete row to application buffers */
- for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;
- bind < end;
- bind++)
- {
+ for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count,
+ field= stmt->fields,
+ field_end= (MYSQL_FIELD *)stmt->fields+stmt->field_count;
+ bind < end && field < field_end;
+ bind++, field++)
+ {
if (*null_ptr & bit)
- bind->is_null= 1;
+ *bind->length= MYSQL_NULL_DATA;
else
- {
- bind->is_null= 0;
- (*bind->fetch_result)(bind, row);
+ {
+ if (field->type == bind->buffer_type)
+ (*bind->fetch_result)(bind, &row);
+ else if (fetch_results(stmt, bind, field->type, &row))
+ break;
}
if (! (bit<<=1) & 255)
{
- bit=1; /* To next byte */
+ bit= 1; /* To next byte */
null_ptr++;
}
}
- return 0;
}
static int read_binary_data(MYSQL *mysql)
-{
+{
+ /* TODO : Changes needed based on logic of use_result/store_result
+ Currently by default it is use_result. In case of
+ store_result, the data packet must point to already
+ read data.
+ */
if (packet_error == net_safe_read(mysql))
return -1;
- if (mysql->net.read_pos[0])
+ if (mysql->net.read_pos[0] == 254)
return 1; /* End of data */
return 0;
}
@@ -4579,29 +4911,24 @@ static int read_binary_data(MYSQL *mysql)
int STDCALL mysql_fetch(MYSQL_STMT *stmt)
{
MYSQL *mysql= stmt->mysql;
+ int res;
DBUG_ENTER("mysql_fetch");
- if (stmt->res_buffers)
+ if (!(res= read_binary_data(mysql)))
{
- int res;
- if (!(res= read_binary_data(mysql)))
- {
- if (stmt->res_buffers)
- DBUG_RETURN((int) stmt_fetch_row(stmt,(uchar **) &mysql->net.read_pos+1));
- DBUG_RETURN(0);
- }
- DBUG_PRINT("info", ("end of data"));
- mysql->status= MYSQL_STATUS_READY;
-
- if (res < 0) /* Network error */
- {
- set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
- mysql->net.last_errno);
- DBUG_RETURN(MYSQL_STATUS_ERROR);
- }
- DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
+ if (stmt->res_buffers)
+ stmt_fetch_row(stmt, mysql->net.read_pos+1);
+ DBUG_RETURN(0);
+ }
+ mysql->status= MYSQL_STATUS_READY;
+ if (res < 0) /* Network error */
+ {
+ set_stmt_errmsg(stmt,(char *)mysql->net.last_error,
+ mysql->net.last_errno);
+ DBUG_RETURN(MYSQL_STATUS_ERROR);
}
- DBUG_RETURN(0); //?? do we need to set MYSQL_STATUS_READY ?
+ DBUG_PRINT("info", ("end of data"));
+ DBUG_RETURN(MYSQL_NO_DATA); /* no more data */
}
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 0be0d624fca..6bfda427f78 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -161,3 +161,74 @@ drop table if exists t1;
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
+drop table if exists t1, t2, t3;
+create table t1(id int not null, name char(20));
+insert into t1 values(10,'mysql'),(20,'monty- the creator');
+create table t2(id int not null);
+insert into t2 values(10),(20);
+create table t3 like t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) character set latin1 default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id name
+create table if not exists t3 like t1;
+Warnings:
+Warning 1050 Table 't3' already exists
+select @@warning_count;
+@@warning_count
+1
+create temporary table t3 like t2;
+show create table t3;
+Table Create Table
+t3 CREATE TEMPORARY TABLE `t3` (
+ `id` int(11) NOT NULL default '0'
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id
+drop table t3;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) character set latin1 default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t3;
+id name
+drop table t2, t3;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.t3 like t1;
+create temporary table t3 like test_$1.t3;
+show create table t3;
+Table Create Table
+t3 CREATE TEMPORARY TABLE `t3` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) character set latin1 default NULL
+) TYPE=MyISAM CHARSET=latin1
+create table t2 like t3;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `name` char(20) character set latin1 default NULL
+) TYPE=MyISAM CHARSET=latin1
+select * from t2;
+id name
+create table t3 like t1;
+create table t3 like test_$1.t3;
+Table 't3' already exists
+create table non_existing_database.t1 like t1;
+Got one of the listed errors
+create table t3 like non_existing_table;
+Unknown table 'non_existing_table'
+create temporary table t3 like t1;
+Table 't3' already exists
+create table t3 like `a/a`;
+Incorrect table name 'a/a'
+drop table t1, t2, t3;
+drop table t3;
+drop database test_$1;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 6a3aa328175..e2d2b1cb652 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -130,3 +130,9 @@ SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
select * from (select 1 as a) b left join (select 2 as a) c using(a);
a a
1 NULL
+SELECT * FROM (SELECT 1 UNION SELECT a) b;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+Unknown column 'a' in 'field list'
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
+Unknown column 'a' in 'field list'
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index ad3a64ccd1d..461ae1e7e09 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -1,6 +1,15 @@
select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0
1
-select old_password('test'),length(password("1")),length(encrypt('test')),encrypt('test','aa');
+select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
+password("a","") password("a",NULL) password("","a") password(NULL,"a")
+*2517f7235d68d4ba2e5019c93420523101157a792c01 NULL NULL
+select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
+password("aaaaaaaaaaaaaaaa","a") password("a","aaaaaaaaaaaaaaaa")
+*2cd3b9a44e9a9994789a30f935c92f45a96c5472f381 *37c7c5c794ff144819f2531bf03c57772cd84e40db09
+select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
old_password('test') length(password("1")) length(encrypt('test')) encrypt('test','aa')
378b243e220ca493 45 13 aaqPiZY5xR5l.
+select old_password(""), old_password(NULL), password(""), password(NULL);
+old_password("") old_password(NULL) password("") password(NULL)
+ NULL NULL
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index d0358aad6ba..429574575f1 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -170,6 +170,9 @@ quote(concat('abc\'', '\\cba'))
select quote(1/0), quote('\0\Z');
quote(1/0) quote('\0\Z')
NULL '\0\Z'
+select length(quote(concat(char(0), "test")));
+length(quote(concat(char(0), "test")))
+8
select reverse("");
reverse("")
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index fe028a4cb95..b037fc87996 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -235,6 +235,21 @@ select * from t2;
n d
1 30
1 30
+UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n;
+select * from t1;
+n d
+1 30
+3 2
+select * from t2;
+n d
+1 30
+1 30
+DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n;
+select * from t1;
+n d
+3 2
+select * from t2;
+n d
drop table t1,t2;
drop table if exists t1,t2,t3;
CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index a37313a150a..ad9294e6d3a 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -531,6 +531,7 @@ i
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
+update t1 set i=(select distinct 1 from (select * from t2) a);
drop table t1, t2, t3;
use mysql;
select * from db;
diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result
new file mode 100644
index 00000000000..a628936b600
--- /dev/null
+++ b/mysql-test/r/rpl_temporary.result
@@ -0,0 +1,74 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop table if exists t1;
+create table t1(f int);
+drop table if exists t2;
+create table t2(f int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+create temporary table t3(f int);
+insert into t3 select * from t1 where f<6;
+create temporary table t3(f int);
+insert into t2 select count(*) from t3;
+insert into t3 select * from t1 where f>=4;
+drop temporary table t3;
+insert into t2 select count(*) from t3;
+drop temporary table t3;
+select * from t2;
+f
+5
+7
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.000001 4 Start 1 4 Server ver: 4.1.0-alpha-debug-log, Binlog ver: 3
+master-bin.000001 79 Query 1 79 use `test`; create table t1(f int)
+master-bin.000001 136 Query 1 136 use `test`; create table t2(f int)
+master-bin.000001 193 Query 1 193 use `test`; insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
+master-bin.000001 290 Query 1 290 use `test`; create temporary table t3(f int)
+master-bin.000001 357 Query 1 357 use `test`; insert into t3 select * from t1 where f<6
+master-bin.000001 433 Query 1 433 use `test`; create temporary table t3(f int)
+master-bin.000001 500 Query 1 500 use `test`; insert into t2 select count(*) from t3
+master-bin.000001 573 Query 1 573 use `test`; insert into t3 select * from t1 where f>=4
+master-bin.000001 650 Query 1 650 use `test`; drop temporary table t3
+master-bin.000001 708 Query 1 708 use `test`; insert into t2 select count(*) from t3
+master-bin.000001 781 Query 1 781 use `test`; drop temporary table t3
+drop table if exists t1;
+drop table if exists t2;
+use test;
+SET TIMESTAMP=1040323920;
+create table t1(f int);
+SET TIMESTAMP=1040323931;
+create table t2(f int);
+SET TIMESTAMP=1040323938;
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+SET TIMESTAMP=1040323945;
+SET @@session.pseudo_thread_id=1;
+create temporary table t3(f int);
+SET TIMESTAMP=1040323952;
+SET @@session.pseudo_thread_id=1;
+insert into t3 select * from t1 where f<6;
+SET TIMESTAMP=1040324145;
+SET @@session.pseudo_thread_id=2;
+create temporary table t3(f int);
+SET TIMESTAMP=1040324186;
+SET @@session.pseudo_thread_id=1;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324200;
+SET @@session.pseudo_thread_id=2;
+insert into t3 select * from t1 where f>=4;
+SET TIMESTAMP=1040324211;
+SET @@session.pseudo_thread_id=1;
+drop temporary table t3;
+SET TIMESTAMP=1040324219;
+SET @@session.pseudo_thread_id=2;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324224;
+SET @@session.pseudo_thread_id=2;
+drop temporary table t3;
+select * from t2;
+f
+5
+7
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index f12e0396694..38a8e0368c6 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1,13 +1,32 @@
select (select 2);
(select 2)
2
+explain select (select 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
SELECT (SELECT 1) UNION SELECT (SELECT 2);
(SELECT 1)
1
2
+explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+Note 1247 Select 4 was reduced during optimisation
SELECT (SELECT (SELECT 0 UNION SELECT 0));
(SELECT (SELECT 0 UNION SELECT 0))
0
+explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
+3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
+4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
Reference 'a' not supported (forward reference in item list)
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -52,6 +71,54 @@ a
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
a
1
+SELECT (SELECT 1,2,3) = ROW(1,2,3);
+(SELECT 1,2,3) = ROW(1,2,3)
+1
+SELECT (SELECT 1,2,3) = ROW(1,2,1);
+(SELECT 1,2,3) = ROW(1,2,1)
+0
+SELECT (SELECT 1,2,3) < ROW(1,2,1);
+(SELECT 1,2,3) < ROW(1,2,1)
+0
+SELECT (SELECT 1,2,3) > ROW(1,2,1);
+(SELECT 1,2,3) > ROW(1,2,1)
+1
+SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
+(SELECT 1,2,3) = ROW(1,2,NULL)
+NULL
+SELECT ROW(1,2,3) = (SELECT 1,2,3);
+ROW(1,2,3) = (SELECT 1,2,3)
+1
+SELECT ROW(1,2,3) = (SELECT 1,2,1);
+ROW(1,2,3) = (SELECT 1,2,1)
+0
+SELECT ROW(1,2,3) < (SELECT 1,2,1);
+ROW(1,2,3) < (SELECT 1,2,1)
+0
+SELECT ROW(1,2,3) > (SELECT 1,2,1);
+ROW(1,2,3) > (SELECT 1,2,1)
+1
+SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
+ROW(1,2,3) = (SELECT 1,2,NULL)
+NULL
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
+(SELECT 1.5,2,'a') = ROW(1.5,2,'a')
+1
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
+(SELECT 1.5,2,'a') = ROW(1.5,2,'b')
+0
+SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
+(SELECT 1.5,2,'a') = ROW('b',2,'b')
+0
+SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
+(SELECT 'b',2,'a') = ROW(1.5,2,'a')
+0
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
+(SELECT 1.5,2,'a') = ROW(1.5,'c','a')
+0
+SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
+(SELECT 1.5,'c','a') = ROW(1.5,2,'a')
+0
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
create table t2 (a int, b int);
@@ -86,20 +153,20 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b
1 7
2 7
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 order by a limit 2) limit 3;
a b
1 7
2 7
3 8
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b
1 7
2 7
3 8
4 8
-explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
@@ -581,12 +648,13 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t ref id id 5 const 1 Using where; Using index
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
+Note 1247 Select 3 was reduced during optimisation
Note 1247 Select 2 was reduced during optimisation
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
-3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
+3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -602,7 +670,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record
-drop table t;
+drop table t, t1;
create table t (a int);
insert into t values (1),(2),(3);
select 1 IN (SELECT * from t);
@@ -704,6 +772,16 @@ NULL
select 10.5 > ANY (SELECT * from t);
10.5 > ANY (SELECT * from t)
1
+explain select (select a+1) from t;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t ALL NULL NULL NULL NULL 3
+Warnings:
+Note 1247 Select 2 was reduced during optimisation
+select (select a+1) from t;
+(select a+1)
+2.5
+NULL
+4.5
drop table t;
create table t (a float);
select 10.5 IN (SELECT * from t LIMIT 1);
@@ -711,3 +789,65 @@ This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
drop table t;
+create table t1 (a int, b int, c varchar(10));
+create table t2 (a int);
+insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
+insert into t2 values (1),(2),(NULL);
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a') (select c from t1 where a=t2.a)
+1 1 a
+2 0 b
+NULL NULL NULL
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b') (select c from t1 where a=t2.a)
+1 0 a
+2 1 b
+NULL NULL NULL
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
+a (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c') (select c from t1 where a=t2.a)
+1 0 a
+2 0 b
+NULL NULL NULL
+drop table t1,t2;
+drop table if exists t;
+create table t (a int, b real, c varchar(10));
+insert into t values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
+select ROW(1, 1, 'a') IN (select a,b,c from t);
+ROW(1, 1, 'a') IN (select a,b,c from t)
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t);
+ROW(1, 2, 'a') IN (select a,b,c from t)
+NULL
+select ROW(1, 1, 'a') IN (select b,a,c from t);
+ROW(1, 1, 'a') IN (select b,a,c from t)
+1
+select ROW(1, 1, 'a') IN (select a,b,c from t where a is not null);
+ROW(1, 1, 'a') IN (select a,b,c from t where a is not null)
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t where a is not null);
+ROW(1, 2, 'a') IN (select a,b,c from t where a is not null)
+0
+select ROW(1, 1, 'a') IN (select b,a,c from t where a is not null);
+ROW(1, 1, 'a') IN (select b,a,c from t where a is not null)
+1
+select ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a');
+ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a')
+1
+select ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a');
+ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a')
+NULL
+select ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a');
+ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a')
+1
+select ROW(1, 1, 'a') IN (select b,a,c from t limit 2);
+This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
+drop table t;
+create table t (a int);
+insert into t values (1);
+do @a:=(SELECT a from t);
+select @a;
+@a
+1
+drop table t;
+do (SELECT a from t);
+Table 'test.t' doesn't exist
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index ba5c1c6e28f..60c975b540e 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -106,9 +106,12 @@ create table t1 (a int not null, b int not null);
insert into t1 values (1,1),(1,2),(1,3);
update t1 set b=4 where a=1 order by b asc limit 1;
update t1 set b=4 where a=1 order by b desc limit 1;
+create table t2 (a int not null, b int not null);
+insert into t2 values (1,1),(1,2),(1,3);
select * from t1;
a b
1 4
1 2
1 4
-drop table t1;
+update t1 set b=(select distinct 1 from (select * from t2) a);
+drop table t1,t2;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 3bad053875c..e057ffaebb0 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -113,3 +113,44 @@ drop table if exists t1;
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
+
+#
+# Test for CREATE TABLE .. LIKE ..
+#
+
+drop table if exists t1, t2, t3;
+create table t1(id int not null, name char(20));
+insert into t1 values(10,'mysql'),(20,'monty- the creator');
+create table t2(id int not null);
+insert into t2 values(10),(20);
+create table t3 like t1;
+show create table t3;
+select * from t3;
+create table if not exists t3 like t1;
+select @@warning_count;
+create temporary table t3 like t2;
+show create table t3;
+select * from t3;
+drop table t3;
+show create table t3;
+select * from t3;
+drop table t2, t3;
+drop database if exists test_$1;
+create database test_$1;
+create table test_$1.t3 like t1;
+create temporary table t3 like test_$1.t3;
+show create table t3;
+create table t2 like t3;
+show create table t2;
+select * from t2;
+create table t3 like t1;
+!$1050 create table t3 like test_$1.t3;
+--error 1044,1
+create table non_existing_database.t1 like t1;
+!$1051 create table t3 like non_existing_table;
+!$1050 create temporary table t3 like t1;
+!$1103 create table t3 like `a/a`;
+drop table t1, t2, t3;
+drop table t3;
+drop database test_$1;
+
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 0c366b65797..8767f9209b3 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -48,3 +48,9 @@ explain select count(*) from t1 as tt1, (select * from t1) as tt2;
drop table if exists t1;
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
select * from (select 1 as a) b left join (select 2 as a) c using(a);
+--error 1054
+SELECT * FROM (SELECT 1 UNION SELECT a) b;
+--error 1054
+SELECT 1 as a FROM (SELECT a UNION SELECT 1) b;
+--error 1054
+SELECT 1 as a FROM (SELECT 1 UNION SELECT a) b;
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index 812bdade39f..af0ef661d06 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -1,3 +1,8 @@
select length(encrypt('foo', 'ff')) <> 0;
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
-select old_password('test'),length(password("1")),length(encrypt('test')),encrypt('test','aa');
+
+# Test new and old password handling functions
+select password("a",""), password("a",NULL), password("","a"), password(NULL,"a");
+select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa");
+select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa');
+select old_password(""), old_password(NULL), password(""), password(NULL);
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index d355cc95317..97b771e7363 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -69,7 +69,7 @@ select decode(encode("abcdef","monty"),"monty")="abcdef";
select quote('\'\"\\test');
select quote(concat('abc\'', '\\cba'));
select quote(1/0), quote('\0\Z');
-
+select length(quote(concat(char(0), "test")));
#
# Wrong usage of functions
#
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 088b355a17c..29239a022ec 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -213,6 +213,12 @@ insert into t2 values(1,10),(1,20);
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
select * from t1;
select * from t2;
+UPDATE t1 a ,t2 b SET a.d=b.d,b.d=30 WHERE a.n=b.n;
+select * from t1;
+select * from t2;
+DELETE t1, t2 FROM t1 a,t2 b where a.n=b.n;
+select * from t1;
+select * from t2;
drop table t1,t2;
drop table if exists t1,t2,t3;
CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test
index c126d221bd2..a944df01051 100644
--- a/mysql-test/t/outfile.test
+++ b/mysql-test/t/outfile.test
@@ -21,3 +21,8 @@
#select * into dumpfile "/tmp/select-test.99" from t1;
#select load_file("/tmp/select-test.not-exist");
#drop table t1;
+#drop table if exists t;
+#CREATE TABLE t ( t timestamp NOT NULL, c char(200) character set latin1 NOT NULL default '', i int(11), v varchar(200), b blob, KEY t (t)) TYPE=MyISAM;
+#INSERT INTO t VALUES ('2002-12-20 12:01:20','',1,"aaa","bbb");
+#select * from t into outfile "check";
+#drop table if exists t;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 6c3f3d6ac52..eeaf1a83d1a 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -368,6 +368,7 @@ select * from t2;
show status like "Qcache_queries_in_cache";
select * from t3;
show status like "Qcache_queries_in_cache";
+update t1 set i=(select distinct 1 from (select * from t2) a);
drop table t1, t2, t3;
#
diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test
new file mode 100644
index 00000000000..1cb53c77f1f
--- /dev/null
+++ b/mysql-test/t/rpl_temporary.test
@@ -0,0 +1,77 @@
+source include/master-slave.inc;
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+drop table if exists t1;
+create table t1(f int);
+drop table if exists t2;
+create table t2(f int);
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+connection con1;
+create temporary table t3(f int);
+insert into t3 select * from t1 where f<6;
+sleep 1;
+
+connection con2;
+create temporary table t3(f int);
+sleep 1;
+
+connection con1;
+insert into t2 select count(*) from t3;
+sleep 1;
+
+connection con2;
+insert into t3 select * from t1 where f>=4;
+sleep 1;
+
+connection con1;
+drop temporary table t3;
+sleep 1;
+
+connection con2;
+insert into t2 select count(*) from t3;
+drop temporary table t3;
+
+select * from t2;
+
+show binlog events;
+
+drop table if exists t1;
+drop table if exists t2;
+
+use test;
+SET TIMESTAMP=1040323920;
+create table t1(f int);
+SET TIMESTAMP=1040323931;
+create table t2(f int);
+SET TIMESTAMP=1040323938;
+insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+SET TIMESTAMP=1040323945;
+SET @@session.pseudo_thread_id=1;
+create temporary table t3(f int);
+SET TIMESTAMP=1040323952;
+SET @@session.pseudo_thread_id=1;
+insert into t3 select * from t1 where f<6;
+SET TIMESTAMP=1040324145;
+SET @@session.pseudo_thread_id=2;
+create temporary table t3(f int);
+SET TIMESTAMP=1040324186;
+SET @@session.pseudo_thread_id=1;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324200;
+SET @@session.pseudo_thread_id=2;
+insert into t3 select * from t1 where f>=4;
+SET TIMESTAMP=1040324211;
+SET @@session.pseudo_thread_id=1;
+drop temporary table t3;
+SET TIMESTAMP=1040324219;
+SET @@session.pseudo_thread_id=2;
+insert into t2 select count(*) from t3;
+SET TIMESTAMP=1040324224;
+SET @@session.pseudo_thread_id=2;
+drop temporary table t3;
+
+select * from t2; \ No newline at end of file
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 347d6276280..de07df1905b 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1,6 +1,9 @@
select (select 2);
+explain select (select 2);
SELECT (SELECT 1) UNION SELECT (SELECT 2);
+explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
SELECT (SELECT (SELECT 0 UNION SELECT 0));
+explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
-- error 1245
SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
-- error 1245
@@ -26,6 +29,22 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
+SELECT (SELECT 1,2,3) = ROW(1,2,3);
+SELECT (SELECT 1,2,3) = ROW(1,2,1);
+SELECT (SELECT 1,2,3) < ROW(1,2,1);
+SELECT (SELECT 1,2,3) > ROW(1,2,1);
+SELECT (SELECT 1,2,3) = ROW(1,2,NULL);
+SELECT ROW(1,2,3) = (SELECT 1,2,3);
+SELECT ROW(1,2,3) = (SELECT 1,2,1);
+SELECT ROW(1,2,3) < (SELECT 1,2,1);
+SELECT ROW(1,2,3) > (SELECT 1,2,1);
+SELECT ROW(1,2,3) = (SELECT 1,2,NULL);
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'a');
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,2,'b');
+SELECT (SELECT 1.5,2,'a') = ROW('b',2,'b');
+SELECT (SELECT 'b',2,'a') = ROW(1.5,2,'a');
+SELECT (SELECT 1.5,2,'a') = ROW(1.5,'c','a');
+SELECT (SELECT 1.5,'c','a') = ROW(1.5,2,'a');
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
@@ -44,11 +63,11 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1);
insert into t3 values (6),(7),(3);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 order by a limit 2) limit 3;
-select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
-explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
+explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
@@ -363,7 +382,7 @@ CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin
INSERT INTO t1 values (1),(1);
-- error 1240
UPDATE t SET id=(SELECT * FROM t1);
-drop table t;
+drop table t, t1;
#NULL test
@@ -408,6 +427,8 @@ select 1.5 > ALL (SELECT * from t);
select 10.5 > ALL (SELECT * from t);
select 1.5 > ANY (SELECT * from t);
select 10.5 > ANY (SELECT * from t);
+explain select (select a+1) from t;
+select (select a+1) from t;
drop table t;
#LIMIT is not supported now
@@ -416,4 +437,37 @@ create table t (a float);
select 10.5 IN (SELECT * from t LIMIT 1);
-- error 1235
select 10.5 IN (SELECT * from t LIMIT 1 UNION SELECT 1.5);
-drop table t; \ No newline at end of file
+drop table t;
+
+create table t1 (a int, b int, c varchar(10));
+create table t2 (a int);
+insert into t1 values (1,2,'a'),(2,3,'b'),(3,4,'c');
+insert into t2 values (1),(2),(NULL);
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),(select c from t1 where a=t2.a) from t2;
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,3,'b'),(select c from t1 where a=t2.a) from t2;
+select a, (select a,b,c from t1 where t1.a=t2.a) = ROW(a,4,'c'),(select c from t1 where a=t2.a) from t2;
+drop table t1,t2;
+
+drop table if exists t;
+create table t (a int, b real, c varchar(10));
+insert into t values (1, 1, 'a'), (2,2,'b'), (NULL, 2, 'b');
+select ROW(1, 1, 'a') IN (select a,b,c from t);
+select ROW(1, 2, 'a') IN (select a,b,c from t);
+select ROW(1, 1, 'a') IN (select b,a,c from t);
+select ROW(1, 1, 'a') IN (select a,b,c from t where a is not null);
+select ROW(1, 2, 'a') IN (select a,b,c from t where a is not null);
+select ROW(1, 1, 'a') IN (select b,a,c from t where a is not null);
+select ROW(1, 1, 'a') IN (select a,b,c from t where c='b' or c='a');
+select ROW(1, 2, 'a') IN (select a,b,c from t where c='b' or c='a');
+select ROW(1, 1, 'a') IN (select b,a,c from t where c='b' or c='a');
+-- error 1235
+select ROW(1, 1, 'a') IN (select b,a,c from t limit 2);
+drop table t;
+
+create table t (a int);
+insert into t values (1);
+do @a:=(SELECT a from t);
+select @a;
+drop table t;
+-- error 1146
+do (SELECT a from t);
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 5cbbd2a350e..24620982cda 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -85,5 +85,8 @@ create table t1 (a int not null, b int not null);
insert into t1 values (1,1),(1,2),(1,3);
update t1 set b=4 where a=1 order by b asc limit 1;
update t1 set b=4 where a=1 order by b desc limit 1;
+create table t2 (a int not null, b int not null);
+insert into t2 values (1,1),(1,2),(1,3);
select * from t1;
-drop table t1;
+update t1 set b=(select distinct 1 from (select * from t2) a);
+drop table t1,t2;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index b6f00daa5cc..c8b7987a506 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -50,7 +50,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
my_getopt.c my_mkdir.c \
default.c my_compress.c checksum.c raid.cc \
my_net.c my_semaphore.c my_port.c \
- my_vsnprintf.c charset.c my_bitmap.c my_bit.c md5.c \
+ my_vsnprintf.c charset.c xml.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
my_handler.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
@@ -103,6 +103,9 @@ test_dir: test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
+test_xml$(EXEEXT): test_xml.c $(LIBRARIES)
+ $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_xml.c $(LDADD) $(LIBS)
+
charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
diff --git a/mysys/charset.c b/mysys/charset.c
index cf0628495fc..f590ee2a49e 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -19,7 +19,9 @@
#include <m_ctype.h>
#include <m_string.h>
#include <my_dir.h>
+#include <my_xml.h>
+#define MY_CHARSET_INDEX "Index.xml"
const char *charsets_dir = NULL;
static int charset_initialized=0;
@@ -85,53 +87,185 @@ char *get_charsets_dir(char *buf)
}
-static my_bool read_charset_index(myf myflags)
+#define MAX_BUF 1024*16
+
+
+static void mstr(char *str,const char *src,uint l1,uint l2)
{
- struct simpleconfig_buf_st fb;
- char buf[MAX_LINE], num_buf[MAX_LINE];
-
- strmov(get_charsets_dir(buf), "Index");
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(str,src,l1);
+ str[l1]='\0';
+}
- if ((fb.f = my_fopen(buf, O_RDONLY, myflags)) == NULL)
- return TRUE;
- fb.buf[0] = '\0';
- fb.p = fb.buf;
+struct my_cs_file_section_st
+{
+ int state;
+ const char *str;
+};
+
+#define _CS_MISC 1
+#define _CS_ID 2
+#define _CS_NAME 3
+#define _CS_FAMILY 4
+#define _CS_ORDER 5
+#define _CS_COLNAME 6
+#define _CS_FLAG 7
+#define _CS_CHARSET 8
+#define _CS_COLLATION 9
+
+static struct my_cs_file_section_st sec[] =
+{
+ {_CS_MISC, "xml"},
+ {_CS_MISC, "xml.version"},
+ {_CS_MISC, "xml.encoding"},
+ {_CS_MISC, "charsets"},
+ {_CS_MISC, "charsets.max-id"},
+ {_CS_MISC, "charsets.description"},
+ {_CS_CHARSET, "charsets.charset"},
+ {_CS_NAME, "charsets.charset.name"},
+ {_CS_FAMILY, "charsets.charset.family"},
+ {_CS_MISC, "charsets.charset.alias"},
+ {_CS_COLLATION, "charsets.charset.collation"},
+ {_CS_COLNAME, "charsets.charset.collation.name"},
+ {_CS_ID, "charsets.charset.collation.id"},
+ {_CS_ORDER, "charsets.charset.collation.order"},
+ {_CS_FLAG, "charsets.charset.collation.flag"},
+ {0, NULL}
+};
+
+static struct my_cs_file_section_st * cs_file_sec(const char *attr, uint len)
+{
+ struct my_cs_file_section_st *s;
+ for (s=sec; s->str; s++)
+ if (!strncmp(attr,s->str,len))
+ return s;
+ return NULL;
+}
+
+struct my_cs_file_info
+{
+ CHARSET_INFO cs;
+ myf myflags;
+};
+
+static int cs_enter(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i = (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s = cs_file_sec(attr,len);
- while (!get_word(&fb, buf) && !get_word(&fb, num_buf))
+ if ( s && (s->state == _CS_CHARSET))
{
- uint csnum;
- uint length;
- CHARSET_INFO *cs;
+ bzero(&i->cs,sizeof(i->cs));
+ }
+ return MY_XML_OK;
+}
- if (!(csnum = atoi(num_buf)))
- {
- /* corrupt Index file */
- my_fclose(fb.f,myflags);
- return TRUE;
- }
-
- if (all_charsets[csnum])
- continue;
-
- if (!(cs=(CHARSET_INFO*) my_once_alloc(sizeof(cs[0]),myflags)))
+static int cs_leave(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i = (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s = cs_file_sec(attr,len);
+ int state = s ? s->state : 0;
+
+ if (state == _CS_COLLATION)
+ {
+ if (!all_charsets[i->cs.number])
{
- my_fclose(fb.f,myflags);
- return TRUE;
+ if (!(all_charsets[i->cs.number]=
+ (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),i->myflags)))
+ {
+ return MY_XML_ERROR;
+ }
+ all_charsets[i->cs.number][0]=i->cs;
}
- bzero(cs,sizeof(cs[0]));
-
- if (!(cs->name= (char*)my_once_alloc(length=(uint)strlen(buf)+1,myflags)))
+ else
{
- my_fclose(fb.f,myflags);
- return TRUE;
+ all_charsets[i->cs.number]->state |= i->cs.state;
}
- memcpy((char*)cs->name,buf,length);
- cs->number=csnum;
- all_charsets[csnum]=cs;
+ i->cs.state=0;
}
- my_fclose(fb.f,myflags);
+ return MY_XML_OK;
+}
+
+static int cs_value(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ struct my_cs_file_info *i = (struct my_cs_file_info *)st->user_data;
+ struct my_cs_file_section_st *s;
+ int state = (s=cs_file_sec(st->attr,strlen(st->attr))) ? s->state : 0;
+
+ if(0)
+ {
+ char str[256];
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("VALUE %d %s='%s'\n",state,st->attr,str);
+ }
+
+ switch (state)
+ {
+ case _CS_ID:
+ i->cs.number = my_strntoul(my_charset_latin1,attr,len,(char**)NULL,0);
+ break;
+ case _CS_COLNAME:
+ if ((i->cs.name = (char*) my_once_alloc(len+1,i->myflags)))
+ {
+ memcpy((char*)i->cs.name,attr,len);
+ ((char*)(i->cs.name))[len]='\0';
+ }
+ break;
+ case _CS_NAME:
+ if ((i->cs.csname = (char*) my_once_alloc(len+1,i->myflags)))
+ {
+ memcpy((char*)i->cs.csname,attr,len);
+ ((char*)(i->cs.csname))[len]='\0';
+ }
+ break;
+ case _CS_FLAG:
+ if (!strncmp("primary",attr,len))
+ i->cs.state |= MY_CS_PRIMARY;
+ }
+ return MY_XML_OK;
+}
+static my_bool read_charset_index(const char *filename, myf myflags)
+{
+ char *buf;
+ int fd;
+ uint len;
+ MY_XML_PARSER p;
+ struct my_cs_file_info i;
+
+ if (! (buf = (char *)my_malloc(MAX_BUF,myflags)))
+ return FALSE;
+
+ strmov(get_charsets_dir(buf),filename);
+
+ if ((fd=my_open(buf,O_RDONLY,myflags)) < 0)
+ {
+ my_free(buf,myflags);
+ return TRUE;
+ }
+
+ len=read(fd,buf,MAX_BUF);
+ my_xml_parser_create(&p);
+ my_close(fd,myflags);
+
+ my_xml_set_enter_handler(&p,cs_enter);
+ my_xml_set_value_handler(&p,cs_value);
+ my_xml_set_leave_handler(&p,cs_leave);
+ my_xml_set_user_data(&p,(void*)&i);
+
+ if (MY_XML_OK!=my_xml_parse(&p,buf,len))
+ {
+ /*
+ printf("ERROR at line %d pos %d '%s'\n",
+ my_xml_error_lineno(&p)+1,
+ my_xml_error_pos(&p),
+ my_xml_error_string(&p));
+ */
+ }
+
+ my_xml_parser_free(&p);
+
return FALSE;
}
@@ -179,7 +313,7 @@ static my_bool init_available_charsets(myf myflags)
if (*cs)
set_max_sort_char(*cs);
}
- error = read_charset_index(myflags);
+ error = read_charset_index(MY_CHARSET_INDEX,myflags);
charset_initialized=1;
pthread_mutex_unlock(&THR_LOCK_charset);
}
@@ -472,7 +606,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags)
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN], cs_string[23];
- strmov(get_charsets_dir(index_file), "Index");
+ strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
cs_string[0]='#';
int10_to_str(cs_number, cs_string+1, 10);
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file);
@@ -505,7 +639,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags)
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
- strmov(get_charsets_dir(index_file), "Index");
+ strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX);
my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file);
}
diff --git a/mysys/test_xml.c b/mysys/test_xml.c
new file mode 100644
index 00000000000..2a679906cbf
--- /dev/null
+++ b/mysys/test_xml.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "my_xml.h"
+
+static void mstr(char *str,const char *src,uint l1,uint l2)
+{
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(str,src,l1);
+ str[l1]='\0';
+}
+
+static int dstr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("VALUE '%s'\n",str);
+ return MY_XML_OK;
+}
+
+static int bstr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("ENTER %s\n",str);
+ return MY_XML_OK;
+}
+
+
+static int estr(MY_XML_PARSER *st,const char *attr, uint len)
+{
+ char str[1024];
+
+ mstr(str,attr,len,sizeof(str)-1);
+ printf("LEAVE %s\n",str);
+ return MY_XML_OK;
+}
+
+static void usage(const char *prog)
+{
+ printf("Usage:\n");
+ printf("%s xmlfile\n",prog);
+}
+
+int main(int ac, char **av)
+{
+ char str[1024*64]="";
+ const char *fn;
+ int f;
+ uint len;
+ MY_XML_PARSER p;
+
+ if (ac<2)
+ {
+ usage(av[0]);
+ return 0;
+ }
+
+ fn=av[1]?av[1]:"test.xml";
+ if ((f=open(fn,O_RDONLY))<0)
+ {
+ fprintf(stderr,"Err '%s'\n",fn);
+ return 1;
+ }
+
+ len=read(f,str,sizeof(str)-1);
+ str[len]='\0';
+
+ my_xml_parser_create(&p);
+
+ my_xml_set_enter_handler(&p,bstr);
+ my_xml_set_value_handler(&p,dstr);
+ my_xml_set_leave_handler(&p,estr);
+
+ if (MY_XML_OK!=(f=my_xml_parse(&p,str,len)))
+ {
+ printf("ERROR at line %d pos %d '%s'\n",
+ my_xml_error_lineno(&p)+1,
+ my_xml_error_pos(&p),
+ my_xml_error_string(&p));
+ }
+
+ my_xml_parser_free(&p);
+
+ return 0;
+}
diff --git a/mysys/xml.c b/mysys/xml.c
new file mode 100644
index 00000000000..4f6301249ae
--- /dev/null
+++ b/mysys/xml.c
@@ -0,0 +1,374 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "my_global.h"
+#include "m_string.h"
+#include "my_xml.h"
+
+
+#define MY_XML_EOF 'E'
+#define MY_XML_STRING 'S'
+#define MY_XML_IDENT 'I'
+#define MY_XML_EQ '='
+#define MY_XML_LT '<'
+#define MY_XML_GT '>'
+#define MY_XML_SLASH '/'
+#define MY_XML_COMMENT 'C'
+#define MY_XML_TEXT 'T'
+#define MY_XML_QUESTION '?'
+#define MY_XML_EXCLAM '!'
+
+typedef struct xml_attr_st
+{
+ const char *beg;
+ const char *end;
+} MY_XML_ATTR;
+
+static const char *lex2str(int lex)
+{
+ switch(lex)
+ {
+ case MY_XML_EOF: return "EOF";
+ case MY_XML_STRING: return "STRING";
+ case MY_XML_IDENT: return "IDENT";
+ case MY_XML_EQ: return "'='";
+ case MY_XML_LT: return "'<'";
+ case MY_XML_GT: return "'>'";
+ case MY_XML_SLASH: return "'/'";
+ case MY_XML_COMMENT: return "COMMENT";
+ case MY_XML_TEXT: return "TEXT";
+ case MY_XML_QUESTION: return "'?'";
+ case MY_XML_EXCLAM: return "'!'";
+ }
+ return "UNKNOWN";
+}
+
+static void my_xml_norm_text(MY_XML_ATTR *a)
+{
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->beg[0]) ; a->beg++ );
+ for ( ; (a->beg < a->end) && strchr(" \t\r\n",a->end[-1]) ; a->end-- );
+}
+
+
+static int my_xml_scan(MY_XML_PARSER *p,MY_XML_ATTR *a)
+{
+ int lex;
+
+ for( ; ( p->cur < p->end) && strchr(" \t\r\n",p->cur[0]) ; p->cur++);
+
+ if (p->cur >= p->end)
+ {
+ a->beg=p->end;
+ a->end=p->end;
+ lex=MY_XML_EOF;
+ goto ret;
+ }
+
+ a->beg=p->cur;
+ a->end=p->cur;
+
+ if (!memcmp(p->cur,"<!--",4))
+ {
+ for( ; (p->cur < p->end) && memcmp(p->cur, "-->", 3); p->cur++);
+ if(!memcmp(p->cur, "-->", 3))
+ p->cur+=3;
+ a->end=p->cur;
+ lex=MY_XML_COMMENT;
+ }
+ else if (strchr("?=/<>!",p->cur[0]))
+ {
+ p->cur++;
+ a->end=p->cur;
+ lex=a->beg[0];
+ }
+ else if ( (p->cur[0]=='"') || (p->cur[0]=='\'') )
+ {
+ p->cur++;
+ for( ; ( p->cur < p->end ) && (p->cur[0]!=a->beg[0]); p->cur++);
+ a->end=p->cur;
+ if (a->beg[0]==p->cur[0])p->cur++;
+ a->beg++;
+ my_xml_norm_text(a);
+ lex=MY_XML_STRING;
+ }
+ else
+ {
+ for( ; (p->cur < p->end) && !strchr("?'\"=/<> \t\r\n", p->cur[0]); p->cur++);
+ a->end=p->cur;
+ my_xml_norm_text(a);
+ lex=MY_XML_IDENT;
+ }
+
+#if 0
+ printf("LEX=%s[%d]\n",lex2str(lex),a->end-a->beg);
+#endif
+
+ret:
+ return lex;
+}
+
+
+static int my_xml_value(MY_XML_PARSER *st, const char *str, uint len)
+{
+ return (st->value) ? (st->value)(st,str,len) : MY_XML_OK;
+}
+
+
+static int my_xml_enter(MY_XML_PARSER *st, const char *str, uint len)
+{
+ if ( (st->attrend-st->attr+len+1)>sizeof(st->attr))
+ {
+ sprintf(st->errstr,"To deep XML");
+ return MY_XML_ERROR;
+ }
+ if (st->attrend > st->attr)
+ {
+ st->attrend[0]='.';
+ st->attrend++;
+ }
+ memcpy(st->attrend,str,len);
+ st->attrend+=len;
+ st->attrend[0]='\0';
+ return st->enter ? st->enter(st,st->attr,st->attrend-st->attr) : MY_XML_OK;
+}
+
+static void mstr(char *s,const char *src,uint l1, uint l2)
+{
+ l1 = l1<l2 ? l1 : l2;
+ memcpy(s,src,l1);
+ s[l1]='\0';
+}
+
+static int my_xml_leave(MY_XML_PARSER *p, const char *str, uint slen)
+{
+ char *e;
+ uint glen;
+ char s[32];
+ char g[32];
+ int rc;
+
+ /* Find previous '.' or beginning */
+ for( e=p->attrend; (e>p->attr) && (e[0]!='.') ; e--);
+ glen = (e[0]=='.') ? (p->attrend-e-1) : p->attrend-e;
+
+ if (str && (slen != glen))
+ {
+ mstr(s,str,sizeof(s)-1,slen);
+ mstr(g,e+1,sizeof(g)-1,glen),
+ sprintf(p->errstr,"'</%s>' unexpected ('</%s>' wanted)",s,g);
+ return MY_XML_ERROR;
+ }
+
+ rc = p->leave ? p->leave(p,p->attr,p->attrend-p->attr) : MY_XML_OK;
+
+ *e='\0';
+ p->attrend=e;
+
+ return rc;
+}
+
+
+int my_xml_parse(MY_XML_PARSER *p,const char *str, uint len)
+{
+ p->attrend=p->attr;
+ p->beg=str;
+ p->cur=str;
+ p->end=str+len;
+
+ while ( p->cur < p->end )
+ {
+ MY_XML_ATTR a;
+ if(p->cur[0]=='<')
+ {
+ int lex;
+ int question=0;
+ int exclam=0;
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_COMMENT==lex)
+ {
+ continue;
+ }
+
+ lex=my_xml_scan(p,&a);
+
+ if (MY_XML_SLASH==lex)
+ {
+ if(MY_XML_IDENT!=(lex=my_xml_scan(p,&a)))
+ {
+ sprintf(p->errstr,"1: %s unexpected (ident wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ goto gt;
+ }
+
+ if (MY_XML_EXCLAM==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ exclam=1;
+ }
+ else if (MY_XML_QUESTION==lex)
+ {
+ lex=my_xml_scan(p,&a);
+ question=1;
+ }
+
+ if (MY_XML_IDENT==lex)
+ {
+ if(MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"3: %s unexpected (ident or '/' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+
+ while ((MY_XML_IDENT==(lex=my_xml_scan(p,&a))) || (MY_XML_STRING==lex))
+ {
+ MY_XML_ATTR b;
+ if(MY_XML_EQ==(lex=my_xml_scan(p,&b)))
+ {
+ lex=my_xml_scan(p,&b);
+ if ( (lex==MY_XML_IDENT) || (lex=MY_XML_STRING) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_value(p,b.beg,b.end-b.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ {
+ sprintf(p->errstr,"4: %s unexpected (ident or string wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else if ( (MY_XML_STRING==lex) || (MY_XML_IDENT==lex) )
+ {
+ if((MY_XML_OK!=my_xml_enter(p,a.beg,a.end-a.beg)) ||
+ (MY_XML_OK!=my_xml_leave(p,a.beg,a.end-a.beg)))
+ return MY_XML_ERROR;
+ }
+ else
+ break;
+ }
+
+ if (lex==MY_XML_SLASH)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+gt:
+ if (question)
+ {
+ if (lex!=MY_XML_QUESTION)
+ {
+ sprintf(p->errstr,"6: %s unexpected ('?' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ lex=my_xml_scan(p,&a);
+ }
+
+ if (exclam)
+ {
+ if(MY_XML_OK!=my_xml_leave(p,NULL,0))
+ return MY_XML_ERROR;
+ }
+
+ if (lex!=MY_XML_GT)
+ {
+ sprintf(p->errstr,"5: %s unexpected ('>' wanted)",lex2str(lex));
+ return MY_XML_ERROR;
+ }
+ }
+ else
+ {
+ a.beg=p->cur;
+ for ( ; (p->cur < p->end) && (p->cur[0]!='<') ; p->cur++);
+ a.end=p->cur;
+
+ my_xml_norm_text(&a);
+ if (a.beg!=a.end)
+ {
+ my_xml_value(p,a.beg,a.end-a.beg);
+ }
+ }
+ }
+ return MY_XML_OK;
+}
+
+void my_xml_parser_create(MY_XML_PARSER *p)
+{
+ bzero((void*)p,sizeof(p[0]));
+}
+
+void my_xml_parser_free(MY_XML_PARSER *p __attribute__((unused)))
+{
+}
+
+void my_xml_set_value_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->value=action;
+}
+
+void my_xml_set_enter_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->enter=action;
+}
+
+void my_xml_set_leave_handler(MY_XML_PARSER *p, int (*action)(MY_XML_PARSER *p, const char *s, uint l))
+{
+ p->leave=action;
+}
+
+void my_xml_set_user_data(MY_XML_PARSER *p, void *user_data)
+{
+ p->user_data=user_data;
+}
+
+const char *my_xml_error_string(MY_XML_PARSER *p)
+{
+ return p->errstr;
+}
+
+
+uint my_xml_error_pos(MY_XML_PARSER *p)
+{
+ const char *beg=p->beg;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ beg=s;
+ return p->cur-beg;
+}
+
+uint my_xml_error_lineno(MY_XML_PARSER *p)
+{
+ uint res=0;
+ const char *s;
+ for ( s=p->beg ; s<p->cur; s++)
+ if (s[0]=='\n')
+ res++;
+ return res;
+}
diff --git a/sql/field.cc b/sql/field.cc
index f206774b456..5f99171b04a 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2599,7 +2599,7 @@ String *Field_double::val_str(String *val_buffer,
bool Field_double::send_binary(Protocol *protocol)
{
- return protocol->store((float) Field_double::val_real(), dec, (String*) 0);
+ return protocol->store((double) Field_double::val_real(), dec, (String*) 0);
}
@@ -2797,7 +2797,6 @@ double Field_timestamp::val_real(void)
longlong Field_timestamp::val_int(void)
{
- uint len,pos;
int part_time;
uint32 temp;
time_t time_arg;
@@ -3169,7 +3168,7 @@ bool Field_time::send_binary(Protocol *protocol)
Field_time::get_time(&tm);
tm.day= tm.hour/3600; // Move hours to days
tm.hour-= tm.day*3600;
- return protocol->store(&tm);
+ return protocol->store_time(&tm);
}
@@ -3254,6 +3253,11 @@ int Field_year::store(longlong nr)
return 0;
}
+bool Field_year::send_binary(Protocol *protocol)
+{
+ ulonglong tmp= Field_year::val_int();
+ return protocol->store_short(tmp);
+}
double Field_year::val_real(void)
{
@@ -3371,6 +3375,16 @@ int Field_date::store(longlong nr)
return error;
}
+bool Field_date::send_binary(Protocol *protocol)
+{
+ longlong tmp= Field_date::val_int();
+ TIME tm;
+ tm.year= (uint32) tmp/10000L % 10000;
+ tm.month= (uint32) tmp/100 % 100;
+ tm.day= (uint32) tmp % 100;
+ return protocol->store_date(&tm);
+}
+
double Field_date::val_real(void)
{
@@ -3544,7 +3558,12 @@ void Field_newdate::store_time(TIME *ltime,timestamp_type type)
int3store(ptr,tmp);
}
-
+bool Field_newdate::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_newdate::get_date(&tm,0);
+ return protocol->store_date(&tm);
+}
double Field_newdate::val_real(void)
{
@@ -3705,6 +3724,13 @@ void Field_datetime::store_time(TIME *ltime,timestamp_type type)
longlongstore(ptr,tmp);
}
+bool Field_datetime::send_binary(Protocol *protocol)
+{
+ TIME tm;
+ Field_datetime::get_date(&tm, 1);
+ return protocol->store(&tm);
+}
+
double Field_datetime::val_real(void)
{
@@ -3926,7 +3952,6 @@ double Field_string::val_real(void)
longlong Field_string::val_int(void)
{
- longlong value;
CHARSET_INFO *cs=charset();
return my_strntoll(cs,ptr,field_length,NULL,10);
}
diff --git a/sql/field.h b/sql/field.h
index 40578d19c82..67bae7302f9 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -166,7 +166,7 @@ public:
ptr-=row_offset;
return tmp;
}
- bool send_binary(Protocol *protocol);
+ virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{
uint32 length=pack_length();
@@ -792,7 +792,6 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void sql_type(String &str) const;
@@ -833,7 +832,6 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
@@ -876,7 +874,6 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
@@ -982,7 +979,6 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
- bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return (uint32) packlength; }
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 8b55a2f4aa1..00ef12839cf 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -496,7 +496,7 @@ static void make_sortkey(register SORTPARAM *param,
length=sort_field->length;
}
#ifdef USE_STRCOLL
- if(use_strnxfrm(cs))
+ if (use_strnxfrm(cs))
{
if (item->binary())
{
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 5a58fef6744..a97ed9cae03 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -3,36 +3,38 @@
int GTextReadStream::get_next_toc_type() const
{
const char *cur = m_cur;
- while((*cur)&&(strchr(" \t\r\n",*cur)))
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
- if(!(*cur))
+ if (!(*cur))
{
return eostream;
}
- if(((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) || (*cur=='_'))
+ if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
+ (*cur=='_'))
{
return word;
}
- if(((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') || (*cur=='.'))
+ if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
+ (*cur=='.'))
{
return numeric;
}
- if(*cur == '(')
+ if (*cur == '(')
{
return l_bra;
}
- if(*cur == ')')
+ if (*cur == ')')
{
return r_bra;
}
- if(*cur == ',')
+ if (*cur == ',')
{
return comma;
}
@@ -43,28 +45,28 @@ int GTextReadStream::get_next_toc_type() const
const char *GTextReadStream::get_next_word(int *word_len)
{
const char *cur = m_cur;
- while((*cur)&&(strchr(" \t\r\n",*cur)))
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
- if(!(*cur))
+ if (!(*cur))
{
return 0;
}
const char *wd_start = cur;
- if(((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
+ if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
{
return NULL;
}
++cur;
- while(((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) || (*cur=='_') ||
- ((*cur>='0') && (*cur<='9')))
+ while (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
+ (*cur=='_') || ((*cur>='0') && (*cur<='9')))
{
++cur;
}
@@ -79,19 +81,19 @@ const char *GTextReadStream::get_next_word(int *word_len)
int GTextReadStream::get_next_number(double *d)
{
const char *cur = m_cur;
- while((*cur)&&(strchr(" \t\r\n",*cur)))
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
- if(!(*cur))
+ if (!(*cur))
{
set_error_msg("Numeric constant expected");
return 1;
}
- if(((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
+ if (((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.'))
{
set_error_msg("Numeric constant expected");
return 1;
@@ -101,7 +103,7 @@ int GTextReadStream::get_next_number(double *d)
*d = strtod(cur, &endptr);
- if(endptr)
+ if (endptr)
{
m_cur = endptr;
}
@@ -112,11 +114,11 @@ int GTextReadStream::get_next_number(double *d)
char GTextReadStream::get_next_symbol()
{
const char *cur = m_cur;
- while((*cur)&&(strchr(" \t\r\n",*cur)))
+ while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
- if(!(*cur))
+ if (!(*cur))
{
return 0;
}
diff --git a/sql/item.cc b/sql/item.cc
index feb318f829d..b0b56bf9101 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -47,11 +47,6 @@ Item::Item():
loop_id= 0;
}
-Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
- char *table_name_par,
- char *field_name_par):
- Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
-
bool Item::check_loop(uint id)
{
@@ -178,7 +173,7 @@ const char *Item_ident::full_name() const
char *tmp;
if (!table_name)
return field_name ? field_name : name ? name : "tmp_field";
- if (db_name)
+ if (db_name && db_name[0])
{
tmp=(char*) sql_alloc((uint) strlen(db_name)+(uint) strlen(table_name)+
(uint) strlen(field_name)+3);
@@ -198,6 +193,7 @@ String *Item_field::val_str(String *str)
{
if ((null_value=field->is_null()))
return 0;
+ str->set_charset(str_value.charset());
return field->val_str(str,&str_value);
}
@@ -220,6 +216,7 @@ String *Item_field::str_result(String *str)
{
if ((null_value=result_field->is_null()))
return 0;
+ str->set_charset(str_value.charset());
return result_field->val_str(str,&str_value);
}
@@ -437,20 +434,6 @@ String *Item_copy_string::val_str(String *str)
return &str_value;
}
-double Item_ref_in_optimizer::val()
-{
- return owner->get_cache();
-}
-longlong Item_ref_in_optimizer::val_int()
-{
- return owner->get_cache_int();
-}
-String* Item_ref_in_optimizer::val_str(String* s)
-{
- return owner->get_cache_str(s);
-}
-
-
/*
Functions to convert item to field (for send_fields)
*/
@@ -464,18 +447,6 @@ bool Item::fix_fields(THD *thd,
return 0;
}
-bool Item_outer_select_context_saver::fix_fields(THD *thd,
- struct st_table_list *list,
- Item ** ref)
-{
- DBUG_ENTER("Item_outer_select_context_saver::fix_fields");
- bool res= item->fix_fields(thd,
- 0, // do not show current subselect fields
- &item);
- *ref= item;
- DBUG_RETURN(res);
-}
-
bool Item_asterisk_remover::fix_fields(THD *thd,
struct st_table_list *list,
Item ** ref)
@@ -529,6 +500,26 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
DBUG_RETURN(res);
}
+bool Item_ref_on_list_position::fix_fields(THD *thd,
+ struct st_table_list *tables,
+ Item ** reference)
+{
+ List_iterator<Item> li(list);
+ Item *item;
+ for (uint i= 0; (item= li++) && i < pos; i++);
+ if (item)
+ {
+ ref= li.ref();
+ return Item_ref_null_helper::fix_fields(thd, tables, reference);
+ }
+ else
+ {
+ ref= 0;
+ my_error(ER_CARDINALITY_COL, MYF(0), pos);
+ return 1;
+ }
+}
+
double Item_ref_null_helper::val()
{
double tmp= (*ref)->val_result();
@@ -556,8 +547,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!field) // If field is not checked
{
- Field *tmp;
- if ((tmp= find_field_in_tables(thd, this, tables, 0)) == not_found_field)
+ TABLE_LIST *where= 0;
+ Field *tmp= (Field *)not_found_field;
+ if (outer_resolving ||
+ (tmp= find_field_in_tables(thd, this, tables, &where, 0)) ==
+ not_found_field)
{
/*
We can't find table field in table list of current select,
@@ -573,14 +567,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Item **refer= (Item **)not_found_item;
// Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
- if (cursel->master_unit()->first_select()->linkage !=
- DERIVED_TABLE_TYPE)
- for (SELECT_LEX *sl=cursel->outer_select();
+ if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
+ for (SELECT_LEX *sl=(outer_resolving?cursel:cursel->outer_select());
sl;
sl= sl->outer_select())
{
if ((tmp= find_field_in_tables(thd, this,
- (last= sl)->get_table_list(),
+ (last= sl)->get_table_list(), &where,
0)) != not_found_field)
break;
if ((refer= find_item_in_list(this, sl->item_list,
@@ -598,7 +591,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else if (tmp == not_found_field && refer == (Item **)not_found_item)
{
// call to return error code
- find_field_in_tables(thd, this, tables, 1);
+ find_field_in_tables(thd, this, tables, &where, 1);
return -1;
}
else if (refer != (Item **)not_found_item)
@@ -608,7 +601,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(char *)field_name);
if (!r)
return 1;
- int res;
if (r->check_cols(1) || r->fix_fields(thd, tables, ref))
return 1;
r->depended_from= last;
@@ -624,6 +616,17 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
found table as depended (of select where was found table)
*/
thd->lex.current_select->mark_as_dependent(last);
+ if (depended_from->having_fix_field)
+ {
+ Item_ref *rf;
+ *ref= rf= new Item_ref((where->db[0]?where->db:0),
+ (char *)where->alias,
+ (char *)field_name);
+ if (!rf)
+ return 1;
+ (rf)->outer_resolving= outer_resolving;
+ return rf->check_cols(1) || rf->fix_fields(thd, tables, ref);
+ }
}
}
else if (!tmp)
@@ -639,14 +642,6 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
table->used_fields++;
table->used_keys&=field->part_of_key;
}
- if (depended_from != 0 && depended_from->having_fix_field)
- {
- *ref= new Item_ref((char *)db_name, (char *)table_name,
- (char *)field_name);
- if (!*ref)
- return 1;
- return (*ref)->check_cols(1) || (*ref)->fix_fields(thd, tables, ref);
- }
fixed= 1;
return 0;
}
@@ -1017,13 +1012,17 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
if (!ref)
{
- SELECT_LEX *sl= thd->lex.current_select->outer_select();
+ TABLE_LIST *where= 0;
+ SELECT_LEX *sl= (outer_resolving?
+ thd->lex.current_select->select_lex():
+ thd->lex.current_select->outer_select());
/*
Finding only in current select will be performed for selects that have
not outer one and for derived tables (which not support using outer
fields for now)
*/
- if ((ref= find_item_in_list(this,
+ if (outer_resolving ||
+ (ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
((sl &&
thd->lex.current_select->master_unit()->
@@ -1051,7 +1050,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
(Item **)not_found_item)
break;
if ((tmp= find_field_in_tables(thd, this,
- sl->get_table_list(),
+ sl->get_table_list(), &where,
0)) != not_found_field);
if (sl->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE)
@@ -1221,6 +1220,141 @@ bool field_is_equal_to_item(Field *field,Item *item)
return result == field->val_real();
}
+Item_cache* Item_cache::get_cache(Item_result type)
+{
+ switch (type)
+ {
+ case INT_RESULT:
+ return new Item_cache_int();
+ case REAL_RESULT:
+ return new Item_cache_real();
+ case STRING_RESULT:
+ return new Item_cache_str();
+ case ROW_RESULT:
+ return new Item_cache_row();
+ default:
+ // should never be in real life
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+void Item_cache_str::store(Item *item)
+{
+ str_value.set(buffer, sizeof(buffer), item->charset());
+ value= item->str_result(&str_value);
+ if ((null_value= item->null_value))
+ value= 0;
+ else if (value != &str_value)
+ {
+ /*
+ We copy string value to avoid changing value if 'item' is table field
+ in queries like following (where t1.c is varchar):
+ select a,
+ (select a,b,c from t1 where t1.a=t2.a) = ROW(a,2,'a'),
+ (select c from t1 where a=t2.a)
+ from t2;
+ */
+ str_value.copy(*value);
+ value= &str_value;
+ }
+
+}
+double Item_cache_str::val()
+{
+ if (value)
+ return my_strntod(value->charset(), value->ptr(),
+ value->length(), (char**)0);
+ else
+ return (double)0;
+}
+longlong Item_cache_str::val_int()
+{
+ if (value)
+ return my_strntoll(value->charset(), value->ptr(),
+ value->length(), (char**) 0, 10);
+ else
+ return (longlong)0;
+}
+
+bool Item_cache_row::allocate(uint num)
+{
+ item_count= num;
+ THD *thd= current_thd;
+ return (!(values=
+ (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count)));
+}
+
+bool Item_cache_row::setup(Item * item)
+{
+ if (!values && allocate(item->cols()))
+ return 1;
+ for (uint i= 0; i < item_count; i++)
+ {
+ Item *el= item->el(i);
+ Item_cache *tmp;
+ if (!(tmp= values[i]= Item_cache::get_cache(el->result_type())))
+ return 1;
+ tmp->setup(el);
+ }
+ return 0;
+}
+
+void Item_cache_row::store(Item * item)
+{
+ null_value= 0;
+ item->bring_value();
+ for (uint i= 0; i < item_count; i++)
+ {
+ values[i]->store(item->el(i));
+ null_value|= values[i]->null_value;
+ }
+}
+
+void Item_cache_row::illegal_method_call(const char *method)
+{
+ DBUG_ENTER("Item_cache_row::illegal_method_call");
+ DBUG_PRINT("error", ("!!! %s method was called for row item", method));
+ DBUG_ASSERT(0);
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
+ DBUG_VOID_RETURN;
+}
+
+bool Item_cache_row::check_cols(uint c)
+{
+ if (c != item_count)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+bool Item_cache_row::null_inside()
+{
+ for (uint i= 0; i < item_count; i++)
+ {
+ if (values[i]->cols() > 1)
+ {
+ if (values[i]->null_inside())
+ return 1;
+ }
+ else
+ {
+ values[i]->val_int();
+ if (values[i]->null_value)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void Item_cache_row::bring_value()
+{
+ for (uint i= 0; i < item_count; i++)
+ values[i]->bring_value();
+ return;
+}
/*****************************************************************************
** Instantiate templates
diff --git a/sql/item.h b/sql/item.h
index 89867a8cdbd..3decdc388eb 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -31,12 +31,12 @@ public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
- enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
- INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
- COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
- PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM,
- FIELD_VARIANCE_ITEM,CONST_ITEM,
- SUBSELECT_ITEM, ROW_ITEM};
+ enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
+ INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
+ COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_ITEM,
+ PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
+ FIELD_VARIANCE_ITEM, CONST_ITEM,
+ SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
String str_value; /* used to store value */
@@ -96,6 +96,7 @@ public:
CHARSET_INFO *thd_charset() const;
CHARSET_INFO *charset() const { return str_value.charset(); };
void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
+ virtual void set_outer_resolving() {}
// Row emulation
virtual uint cols() { return 1; }
@@ -103,64 +104,12 @@ public:
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
// It is not row => null inside is impossible
- virtual bool null_inside() { return 0; };
+ virtual bool null_inside() { return 0; }
+ // used in row subselects to get value of elements
+ virtual void bring_value() {}
};
-/*
- Wrapper base class
-*/
-
-class Item_wrapper :public Item
-{
-protected:
- Item *item;
-public:
- /*
- Following methods should not be used, because fix_fields exclude this
- item (it assign '*ref' with field 'item' in derived classes)
- */
- enum Type type() const { return item->type(); }
- enum_field_types field_type() const { return item->field_type(); }
- double val() { return item->val(); }
- longlong val_int() { return item->val_int(); }
- String* val_str(String* s) { return item->val_str(s); }
- bool check_cols(uint col) { return item->check_cols(col); }
- bool eq(const Item *item, bool binary_cmp) const
- { return item->eq(item, binary_cmp); }
- bool is_null()
- {
- item->val_int();
- return item->null_value;
- }
- bool get_date(TIME *ltime, bool fuzzydate)
- {
- return (null_value=item->get_date(ltime, fuzzydate));
- }
- bool send(Protocol *prot, String *tmp) { return item->send(prot, tmp); }
- int save_in_field(Field *field, bool no_conversions)
- {
- return item->save_in_field(field, no_conversions);
- }
- void save_org_in_field(Field *field) { item->save_org_in_field(field); }
- enum Item_result result_type () const { return item->result_type(); }
- table_map used_tables() const { return item->used_tables(); }
-};
-
-
-/*
- Save context of name resolution for Item, used in subselect transformer.
-*/
-class Item_outer_select_context_saver :public Item_wrapper
-{
-public:
- Item_outer_select_context_saver(Item *it)
- {
- item= it;
- }
- bool fix_fields(THD *, struct st_table_list *, Item ** ref);
-};
-
class st_select_lex;
class Item_ident :public Item
{
@@ -169,12 +118,14 @@ public:
const char *table_name;
const char *field_name;
st_select_lex *depended_from;
+ bool outer_resolving; /* used for items from reduced subselect */
Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
- :db_name(db_name_par),table_name(table_name_par),
- field_name(field_name_par), depended_from(0)
+ :db_name(db_name_par), table_name(table_name_par),
+ field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; }
const char *full_name() const;
+ void set_outer_resolving() { outer_resolving= 1; }
};
@@ -381,7 +332,7 @@ public:
name=(char*) str_value.ptr();
decimals=NOT_FIXED_DEC;
}
- Item_string(const char *name_par,const char *str,uint length,
+ Item_string(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs)
{
str_value.set(str,length,cs);
@@ -393,11 +344,13 @@ public:
enum Type type() const { return STRING_ITEM; }
double val()
{
- return my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),(char**)NULL);
+ return my_strntod(str_value.charset(), str_value.ptr(),
+ str_value.length(), (char**) 0);
}
longlong val_int()
{
- return my_strntoll(str_value.charset(),str_value.ptr(),str_value.length(),(char**) 0,10);
+ return my_strntoll(str_value.charset(), str_value.ptr(),
+ str_value.length(), (char**) 0, 10);
}
String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions);
@@ -551,7 +504,7 @@ protected:
Item_in_subselect* owner;
public:
Item_ref_null_helper(Item_in_subselect* master, Item **item,
- char *table_name_par,char *field_name_par):
+ char *table_name_par, char *field_name_par):
Item_ref(item, table_name_par, field_name_par), owner(master) {}
double val();
longlong val_int();
@@ -559,6 +512,28 @@ public:
bool get_date(TIME *ltime, bool fuzzydate);
};
+
+/*
+ Used to find item in list of select items after '*' items processing.
+
+ Because item '*' can be used in item list. when we create
+ Item_ref_on_list_position we do not know how item list will be changed, but
+ we know number of item position (I mean queries like "select * from t").
+*/
+class Item_ref_on_list_position: public Item_ref_null_helper
+{
+protected:
+ List<Item> &list;
+ uint pos;
+public:
+ Item_ref_on_list_position(Item_in_subselect* master,
+ List<Item> &li, uint num,
+ char *table_name, char *field_name):
+ Item_ref_null_helper(master, 0, table_name, field_name),
+ list(li), pos(num) {}
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+};
+
/*
To resolve '*' field moved to condition
and register NULL values
@@ -575,24 +550,6 @@ public:
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
-class Item_in_optimizer;
-class Item_ref_in_optimizer: public Item_ref
-{
-protected:
- Item_in_optimizer* owner;
-public:
- Item_ref_in_optimizer(Item_in_optimizer* master,
- char *table_name_par,char *field_name_par);
- double val();
- longlong val_int();
- String* val_str(String* s);
- bool fix_fields(THD *, struct st_table_list *, Item ** ref)
- {
- fixed= 1;
- return 0;
- }
-};
-
/*
The following class is used to optimize comparing of date columns
We need to save the original item, to be able to set the field to the
@@ -707,6 +664,122 @@ public:
bool cmp(void);
};
+class Item_cache: public Item
+{
+public:
+ virtual bool allocate(uint i) { return 0; };
+ virtual bool setup(Item *) { return 0; };
+ virtual void store(Item *)= 0;
+ void set_len_n_dec(uint32 max_len, uint8 dec)
+ {
+ max_length= max_len;
+ decimals= dec;
+ }
+ enum Type type() const { return CACHE_ITEM; }
+ static Item_cache* get_cache(Item_result type);
+};
+
+class Item_cache_int: public Item_cache
+{
+ longlong value;
+public:
+ Item_cache_int() { fixed= 1; null_value= 1; }
+
+ void store(Item *item)
+ {
+ value= item->val_int_result();
+ null_value= item->null_value;
+ }
+ double val() { return (double) value; }
+ longlong val_int() { return value; }
+ String* val_str(String *str) { str->set(value, thd_charset()); return str; }
+ enum Item_result result_type() const { return INT_RESULT; }
+};
+
+class Item_cache_real: public Item_cache
+{
+ double value;
+public:
+ Item_cache_real() { fixed= 1; null_value= 1; }
+
+ void store(Item *item)
+ {
+ value= item->val_result();
+ null_value= item->null_value;
+ }
+ double val() { return value; }
+ longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
+ String* val_str(String *str)
+ {
+ str->set(value, decimals, thd_charset());
+ return str;
+ }
+ enum Item_result result_type() const { return REAL_RESULT; }
+};
+
+class Item_cache_str: public Item_cache
+{
+ char buffer[80];
+ String *value;
+public:
+ Item_cache_str() { fixed= 1; null_value= 1; }
+
+ void store(Item *item);
+ double val();
+ longlong val_int();
+ String* val_str(String *) { return value; }
+ enum Item_result result_type() const { return STRING_RESULT; }
+ CHARSET_INFO *charset() const { return value->charset(); };
+};
+
+class Item_cache_row: public Item_cache
+{
+ Item_cache **values;
+ uint item_count;
+public:
+ Item_cache_row(): values(0), item_count(2) { fixed= 1; null_value= 1; }
+
+ /*
+ 'allocate' used only in row transformer, to preallocate space for row
+ cache.
+ */
+ bool allocate(uint num);
+ /*
+ 'setup' is needed only by row => it not called by simple row subselect
+ (only by IN subselect (in subselect optimizer))
+ */
+ bool setup(Item *item);
+ void store(Item *item);
+ void illegal_method_call(const char *);
+ void make_field(Send_field *)
+ {
+ illegal_method_call((const char*)"make_field");
+ };
+ double val()
+ {
+ illegal_method_call((const char*)"val");
+ return 0;
+ };
+ longlong val_int()
+ {
+ illegal_method_call((const char*)"val_int");
+ return 0;
+ };
+ String *val_str(String *)
+ {
+ illegal_method_call((const char*)"val_str");
+ return 0;
+ };
+ enum Item_result result_type() const { return ROW_RESULT; }
+
+ uint cols() { return item_count; }
+ Item* el(uint i) { return values[i]; }
+ Item** addr(uint i) { return (Item **) (values + i); }
+ bool check_cols(uint c);
+ bool null_inside();
+ void bring_value();
+};
+
extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index eb3df461603..3d65c05b9cf 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -153,11 +153,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
}
else
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- current_thd->fatal_error= 1;
return 1;
- }
}
return 0;
}
@@ -247,6 +243,8 @@ int Arg_comparator::compare_e_int()
int Arg_comparator::compare_row()
{
int res= 0;
+ (*a)->bring_value();
+ (*b)->bring_value();
uint n= (*a)->cols();
for (uint i= 0; i<n; i++)
{
@@ -261,6 +259,8 @@ int Arg_comparator::compare_row()
int Arg_comparator::compare_e_row()
{
int res= 0;
+ (*a)->bring_value();
+ (*b)->bring_value();
uint n= (*a)->cols();
for (uint i= 0; i<n; i++)
{
@@ -270,60 +270,59 @@ int Arg_comparator::compare_e_row()
return 1;
}
-longlong Item_in_optimizer::val_int()
+bool Item_in_optimizer::preallocate_row()
{
- int_cache_ok= 1;
- flt_cache_ok= 0;
- str_cache_ok= 0;
- int_cache= args[0]->val_int_result();
- if (args[0]->null_value)
- {
- null_value= 1;
- return 0;
- }
- longlong tmp= args[1]->val_int_result();
- null_value= args[1]->null_value;
- return tmp;
+ return (!(cache= Item_cache::get_cache(ROW_RESULT)));
}
-longlong Item_in_optimizer::get_cache_int()
+bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
+ Item ** ref)
{
- if (!int_cache_ok)
+ if (args[0]->fix_fields(thd, tables, args))
+ return 1;
+ if (args[0]->maybe_null)
+ maybe_null=1;
+ if (args[0]->binary())
+ set_charset(my_charset_bin);
+ with_sum_func= args[0]->with_sum_func;
+ used_tables_cache= args[0]->used_tables();
+ const_item_cache= args[0]->const_item();
+ if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
+ return 1;
+ cache->setup(args[0]);
+ if (args[1]->fix_fields(thd, tables, args))
+ return 1;
+ Item_in_subselect * sub= (Item_in_subselect *)args[1];
+ if (args[0]->cols() != sub->engine->cols())
{
- int_cache_ok= 1;
- flt_cache_ok= 0;
- str_cache_ok= 0;
- int_cache= args[0]->val_int_result();
- null_value= args[0]->null_value;
+ my_error(ER_CARDINALITY_COL, MYF(0), args[0]->cols());
+ return 1;
}
- return int_cache;
+ if (args[1]->maybe_null)
+ maybe_null=1;
+ with_sum_func= with_sum_func || args[1]->with_sum_func;
+ used_tables_cache|= args[1]->used_tables();
+ const_item_cache&= args[1]->const_item();
+ return 0;
}
-double Item_in_optimizer::get_cache()
+longlong Item_in_optimizer::val_int()
{
- if (!flt_cache_ok)
+ cache->store(args[0]);
+ if (cache->null_value)
{
- flt_cache_ok= 1;
- int_cache_ok= 0;
- str_cache_ok= 0;
- flt_cache= args[0]->val_result();
- null_value= args[0]->null_value;
+ null_value= 1;
+ return 0;
}
- return flt_cache;
+ longlong tmp= args[1]->val_int_result();
+ null_value= args[1]->null_value;
+ return tmp;
}
-String *Item_in_optimizer::get_cache_str(String *s)
+bool Item_in_optimizer::is_null()
{
- if (!str_cache_ok)
- {
- str_cache_ok= 1;
- int_cache_ok= 0;
- flt_cache_ok= 0;
- str_value.set(buffer, sizeof(buffer), s->charset());
- str_cache= args[0]->str_result(&str_value);
- null_value= args[0]->null_value;
- }
- return str_cache;
+ cache->store(args[0]);
+ return (null_value= (cache->null_value || args[1]->is_null()));
}
longlong Item_func_eq::val_int()
@@ -936,6 +935,13 @@ Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return 0;
}
+void Item_func_case::set_outer_resolving()
+{
+ first_expr->set_outer_resolving();
+ else_expr->set_outer_resolving();
+ Item_func::set_outer_resolving();
+}
+
bool Item_func_case::check_loop(uint id)
{
DBUG_ENTER("Item_func_case::check_loop");
@@ -1218,8 +1224,9 @@ void cmp_item_row::store_value(Item *item)
{
THD *thd= current_thd;
n= item->cols();
- if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
+ if ((comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *)*n)))
{
+ item->bring_value();
item->null_value= 0;
for (uint i=0; i < n; i++)
if ((comparators[i]= cmp_item::get_comparator(item->el(i))))
@@ -1228,18 +1235,10 @@ void cmp_item_row::store_value(Item *item)
item->null_value|= item->el(i)->null_value;
}
else
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- thd->fatal_error= 1;
return;
- }
}
else
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- thd->fatal_error= 1;
return;
- }
}
void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
@@ -1253,6 +1252,7 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
n= tmpl->n;
if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
{
+ item->bring_value();
item->null_value= 0;
for (uint i=0; i < n; i++)
if ((comparators[i]= tmpl->comparators[i]->make_same()))
@@ -1262,18 +1262,10 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
item->null_value|= item->el(i)->null_value;
}
else
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- current_thd->fatal_error= 1;
return;
- }
}
else
- {
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- current_thd->fatal_error= 1;
return;
- }
}
int cmp_item_row::cmp(Item *arg)
@@ -1285,6 +1277,7 @@ int cmp_item_row::cmp(Item *arg)
return 1;
}
bool was_null= 0;
+ arg->bring_value();
for (uint i=0; i < n; i++)
if (comparators[i]->cmp(arg->el(i)))
{
@@ -1510,6 +1503,15 @@ bool Item_cond::check_loop(uint id)
DBUG_RETURN(0);
}
+void Item_cond::set_outer_resolving()
+{
+ Item_func::set_outer_resolving();
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ item->set_outer_resolving();
+}
+
void Item_cond::split_sum_func(List<Item> &fields)
{
List_iterator<Item> li(list);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 994e51ef89f..bd7d1bfaf7a 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -85,25 +85,28 @@ public:
void fix_length_and_dec() { decimals=0; max_length=1; }
};
+class Item_cache;
class Item_in_optimizer: public Item_bool_func
{
protected:
- char buffer[80];
- longlong int_cache;
- double flt_cache;
- String *str_cache;
- bool int_cache_ok, flt_cache_ok, str_cache_ok;
-public:
- Item_in_optimizer(Item *a,Item *b):
- Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {}
- bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
+ Item_cache *cache;
+public:
+ Item_in_optimizer(Item *a, Item_in_subselect *b):
+ Item_bool_func(a, (Item *)b), cache(0) {}
+ // used by row in transformer
+ bool preallocate_row();
+ bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool is_null();
+ /*
+ Item_in_optimizer item is special boolean function. On value request
+ (one of val, val_int or val_str methods) it evaluate left expression
+ of IN by storing it value in cache item (one of Item_cache* items),
+ then it test cache is it NULL. If left expression (cache) is NULL then
+ Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
+ */
longlong val_int();
-
- double get_cache();
- longlong get_cache_int();
- String *get_cache_str(String *s);
-
- friend class Item_ref_in_optimizer;
+
+ Item_cache **get_cache() { return &cache; }
};
class Item_bool_func2 :public Item_int_func
@@ -281,6 +284,11 @@ public:
const char *func_name() const { return "interval"; }
void update_used_tables();
bool check_loop(uint id);
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_func::set_outer_resolving();
+ }
};
@@ -363,6 +371,7 @@ public:
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
Item *find_item(String *str);
bool check_loop(uint id);
+ void set_outer_resolving();
};
@@ -542,10 +551,14 @@ public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row()
{
- if(comparators)
- for(uint i= 0; i < n; i++)
+ if (comparators)
+ {
+ for (uint i= 0; i < n; i++)
+ {
if (comparators[i])
delete comparators[i];
+ }
+ }
}
void store_value(Item *item);
int cmp(Item *arg);
@@ -647,6 +660,11 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(item->check_loop(id));
}
bool nulls_in_row();
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_int_func::set_outer_resolving();
+ }
};
/* Functions used by where clause */
@@ -788,6 +806,7 @@ public:
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id);
void top_level_item() { abort_on_null=1; }
+ void set_outer_resolving();
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 40579646ae8..dcf4638c48a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -146,6 +146,16 @@ bool Item_func::check_loop(uint id)
DBUG_RETURN(0);
}
+void Item_func::set_outer_resolving()
+{
+ if (arg_count)
+ {
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
+ (*arg)->set_outer_resolving();
+ }
+}
+
void Item_func::split_sum_func(List<Item> &fields)
{
Item **arg,**arg_end;
@@ -2359,6 +2369,15 @@ bool Item_func_match::check_loop(uint id)
DBUG_RETURN(0);
}
+void Item_func_match::set_outer_resolving()
+{
+ Item_real_func::set_outer_resolving();
+ List_iterator<Item> li(fields);
+ Item *item;
+ while ((item= li++))
+ item->set_outer_resolving();
+}
+
bool Item_func_match::fix_index()
{
List_iterator_fast<Item> li(fields);
diff --git a/sql/item_func.h b/sql/item_func.h
index a5420f9056c..bf64412cab3 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -133,6 +133,7 @@ public:
friend class udf_handler;
Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id);
+ void set_outer_resolving();
};
@@ -632,6 +633,11 @@ public:
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_int_func::set_outer_resolving();
+ }
};
@@ -988,7 +994,7 @@ public:
{
ft_handler->please->close_search(ft_handler);
ft_handler=0;
- if(join_key)
+ if (join_key)
table->file->ft_handler=0;
table->fulltext_searched=0;
}
@@ -1005,6 +1011,7 @@ public:
bool fix_index();
void init_search(bool no_order);
bool check_loop(uint id);
+ void set_outer_resolving();
};
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 85a81a50256..c62ab60c0cd 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -41,7 +41,7 @@ void Item_row::illegal_method_call(const char *method)
DBUG_ENTER("Item_row::illegal_method_call");
DBUG_PRINT("error", ("!!! %s method was called for row item", method));
DBUG_ASSERT(0);
- my_error(ER_CARDINALITY_COL, MYF(0), arg_count);
+ my_error(ER_CARDINALITY_COL, MYF(0), 1);
DBUG_VOID_RETURN;
}
@@ -54,7 +54,16 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
if (items[i]->fix_fields(thd, tabl, items+i))
return 1;
used_tables_cache |= items[i]->used_tables();
- const_item_cache&= items[i]->const_item();
+ if (const_item_cache&= items[i]->const_item() && !with_null)
+ {
+ if (items[i]->cols() > 1)
+ with_null|= items[i]->null_inside();
+ else
+ {
+ items[i]->val_int();
+ with_null|= items[i]->null_value;
+ }
+ }
maybe_null|= items[i]->maybe_null;
}
return 0;
@@ -82,21 +91,24 @@ bool Item_row::check_cols(uint c)
return 0;
}
-bool Item_row::null_inside()
+void Item_row::bring_value()
{
for (uint i= 0; i < arg_count; i++)
- {
- if (items[i]->cols() > 1)
- {
- if (items[i]->null_inside())
- return 1;
- }
- else
- {
- items[i]->val_int();
- if (items[i]->null_value)
- return 1;
- }
- }
+ items[i]->bring_value();
+}
+
+void Item_row::set_outer_resolving()
+{
+ for (uint i= 0; i < arg_count; i++)
+ items[i]->set_outer_resolving();
+}
+
+bool Item_row::check_loop(uint id)
+{
+ if (Item::check_loop(id))
+ return 1;
+ for (uint i= 0; i < arg_count; i++)
+ if (items[i]->check_loop(id))
+ return 1;
return 0;
}
diff --git a/sql/item_row.h b/sql/item_row.h
index 4767d19d08f..ccaf68bed64 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -16,24 +16,27 @@
class Item_row: public Item
{
- bool array_holder;
+ Item **items;
table_map used_tables_cache;
- bool const_item_cache;
uint arg_count;
- Item **items;
+ bool array_holder;
+ bool const_item_cache;
+ bool with_null;
public:
Item_row(List<Item> &);
Item_row(Item_row *item):
- Item(), array_holder(0),
+ Item(),
+ items(item->items),
used_tables_cache(item->used_tables_cache),
- const_item_cache(item->const_item_cache),
arg_count(item->arg_count),
- items(item->items)
+ array_holder(0),
+ const_item_cache(item->const_item_cache),
+ with_null(0)
{}
~Item_row()
{
- if(array_holder && items)
+ if (array_holder && items)
sql_element_free(items);
}
@@ -64,10 +67,13 @@ public:
bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables();
+ bool check_loop(uint id);
+ void set_outer_resolving();
uint cols() { return arg_count; }
Item* el(uint i) { return items[i]; }
Item** addr(uint i) { return items + i; }
bool check_cols(uint c);
- bool null_inside();
+ bool null_inside() { return with_null; };
+ void bring_value();
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 78689bb3044..d2b0e89254e 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1271,18 +1271,60 @@ String *Item_func_trim::val_str(String *str)
return &tmp_value;
}
+/*
+ Password() function can have 2 args now. Second argument can be used
+ to make results repeatable
+*/
String *Item_func_password::val_str(String *str)
{
- String *res =args[0]->val_str(str);
+ struct rand_struct rand_st; // local structure for 2 param version
+ ulong seed=0; // seed to initialise random generator to
+
+ String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
- if (res->length() == 0)
- return &empty_string;
- make_scrambled_password(tmp_value,res->c_ptr(),opt_old_passwords,
- &current_thd->rand);
- str->set(tmp_value,get_password_length(opt_old_passwords),res->charset());
- return str;
+
+ if (arg_count == 1)
+ {
+ if (res->length() == 0)
+ return &empty_string;
+ make_scrambled_password(tmp_value,res->c_ptr(),opt_old_passwords,
+ &current_thd->rand);
+ str->set(tmp_value,get_password_length(opt_old_passwords),res->charset());
+ return str;
+ }
+ else
+ {
+ /* We'll need the buffer to get second parameter */
+ char key_buff[80];
+ String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
+ String *key =args[1]->val_str(&tmp_key_value);
+
+ /* Check second argument for NULL value. First one is already checked */
+ if ((null_value=args[1]->null_value))
+ return 0;
+
+ /* This shall be done after checking for null for proper results */
+ if (res->length() == 0)
+ return &empty_string;
+
+ /* Generate the seed first this allows to avoid double allocation */
+ char* seed_ptr=key->c_ptr();
+ while (*seed_ptr)
+ {
+ seed=seed*211+*seed_ptr; /* Use simple hashing */
+ seed_ptr++;
+ }
+
+ /* Use constants which allow nice random values even with small seed */
+ randominit(&rand_st,seed*111111+33333333L,seed*1111+55555555L);
+
+ make_scrambled_password(tmp_value,res->c_ptr(),opt_old_passwords,
+ &rand_st);
+ str->set(tmp_value,get_password_length(opt_old_passwords),res->charset());
+ return str;
+ }
}
String *Item_func_old_password::val_str(String *str)
@@ -1961,7 +2003,8 @@ String *Item_func_conv_charset::val_str(String *str)
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
- while( s < se && d < de){
+ while (s < se && d < de)
+ {
cnvres=from->mb_wc(from,&wc,s,se);
if (cnvres>0)
@@ -2035,7 +2078,7 @@ String *Item_func_conv_charset3::val_str(String *str)
d0=d=(unsigned char*)str->ptr();
de=d+dmaxlen;
- while( s < se && d < de){
+ while (s < se && d < de){
cnvres=from_charset->mb_wc(from_charset,&wc,s,se);
if (cnvres>0)
@@ -2397,7 +2440,7 @@ String *Item_func_quote::val_str(String *str)
*/
to= (char*) str->ptr() + new_length - 1;
*to--= '\'';
- for (start= (char*) arg->ptr() ; end-- != start; to--)
+ for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--)
{
/*
We can't use the bitmask here as we want to replace \O and ^Z with 0
@@ -2655,7 +2698,7 @@ String *Item_func_spatial_collection::val_str(String *str)
null_value=1;
str->length(0);
- if(str->reserve(9,512))
+ if (str->reserve(9,512))
return 0;
str->q_append((char)Geometry::wkbNDR);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index c8706c2c933..c90ff6e2295 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -108,14 +108,19 @@ public:
separator->fix_fields(thd, tlist, &separator) ||
Item_func::fix_fields(thd, tlist, ref));
}
- const char *func_name() const { return "concat_ws"; }
- bool check_loop(uint id)
- {
- DBUG_ENTER("Item_func_concat_ws::check_loop");
- if (Item_str_func::check_loop(id))
- DBUG_RETURN(1);
- DBUG_RETURN(separator->check_loop(id));
- }
+ const char *func_name() const { return "concat_ws"; }
+ bool check_loop(uint id)
+ {
+ DBUG_ENTER("Item_func_concat_ws::check_loop");
+ if (Item_str_func::check_loop(id))
+ DBUG_RETURN(1);
+ DBUG_RETURN(separator->check_loop(id));
+ }
+ void set_outer_resolving()
+ {
+ separator->set_outer_resolving();
+ Item_func::set_outer_resolving();
+ }
};
class Item_func_reverse :public Item_str_func
@@ -257,6 +262,7 @@ class Item_func_password :public Item_str_func
char tmp_value[64]; /* This should be enough for new password format */
public:
Item_func_password(Item *a) :Item_str_func(a) {}
+ Item_func_password(Item *a, Item *b) :Item_str_func(a,b) {}
String *val_str(String *);
void fix_length_and_dec() { max_length = get_password_length(opt_old_passwords); }
const char *func_name() const { return "password"; }
@@ -393,6 +399,11 @@ public:
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_str_func::set_outer_resolving();
+ }
};
@@ -421,6 +432,11 @@ public:
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
+ void set_outer_resolving()
+ {
+ item->set_outer_resolving();
+ Item_str_func::set_outer_resolving();
+ }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4b9e9c256d1..c5ecdc87d40 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -32,6 +32,11 @@ SUBSELECT TODO:
#include "mysql_priv.h"
#include "sql_select.h"
+inline Item * and_items(Item* cond, Item *item)
+{
+ return (cond? (new Item_cond_and(cond, item)) : item);
+}
+
Item_subselect::Item_subselect():
Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
have_to_be_excluded(0)
@@ -51,7 +56,7 @@ void Item_subselect::init(THD *thd, st_select_lex *select_lex,
DBUG_ENTER("Item_subselect::init");
DBUG_PRINT("subs", ("select_lex 0x%xl", (ulong) select_lex));
- select_transformer(select_lex);
+ select_transformer(thd, select_lex->master_unit());
if (select_lex->next_select())
engine= new subselect_union_engine(thd, select_lex->master_unit(), result,
this);
@@ -67,7 +72,7 @@ Item_subselect::~Item_subselect()
delete engine;
}
-void Item_subselect::select_transformer(st_select_lex *select_lex)
+void Item_subselect::select_transformer(THD *thd, st_select_lex_unit *unit)
{
DBUG_ENTER("Item_subselect::select_transformer");
DBUG_VOID_RETURN;
@@ -112,9 +117,14 @@ bool Item_subselect::check_loop(uint id)
DBUG_RETURN(engine->check_loop(id));
}
+Item::Type Item_subselect::type() const
+{
+ return SUBSELECT_ITEM;
+}
+
void Item_subselect::fix_length_and_dec()
{
- engine->fix_length_and_dec();
+ engine->fix_length_and_dec(0);
}
inline table_map Item_subselect::used_tables() const
@@ -122,56 +132,165 @@ inline table_map Item_subselect::used_tables() const
return (table_map) engine->depended() ? 1L : 0L;
}
-Item_singleval_subselect::Item_singleval_subselect(THD *thd,
+Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
st_select_lex *select_lex):
- Item_subselect()
+ Item_subselect(), value(0)
{
- DBUG_ENTER("Item_singleval_subselect::Item_singleval_subselect");
- init(thd, select_lex, new select_singleval_subselect(this));
+ DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect");
+ init(thd, select_lex, new select_singlerow_subselect(this));
max_columns= 1;
maybe_null= 1;
+ max_columns= UINT_MAX;
DBUG_VOID_RETURN;
}
-void Item_singleval_subselect::fix_length_and_dec()
+void Item_singlerow_subselect::reset()
{
- engine->fix_length_and_dec();
- res_type= engine->type();
+ null_value= 1;
+ if (value)
+ value->null_value= 1;
}
-Item::Type Item_subselect::type() const
+void Item_singlerow_subselect::select_transformer(THD *thd,
+ st_select_lex_unit *unit)
{
- return SUBSELECT_ITEM;
+ SELECT_LEX *select_lex= unit->first_select();
+
+ if (!select_lex->next_select() && !select_lex->table_list.elements &&
+ select_lex->item_list.elements == 1 &&
+ // TODO: mark subselect items from item list separately
+ !(select_lex->item_list.head()->type() == FIELD_ITEM ||
+ select_lex->item_list.head()->type() == REF_ITEM)
+ )
+ {
+
+ have_to_be_excluded= 1;
+ if (thd->lex.describe)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_SELECT_REDUCED, warn_buff);
+ }
+ substitution= select_lex->item_list.head();
+ substitution->set_outer_resolving();
+
+ if (select_lex->where || select_lex->having)
+ {
+ Item *cond;
+ if (!select_lex->having)
+ cond= select_lex->where;
+ else if (!select_lex->where)
+ cond= select_lex->having;
+ else
+ if (!(cond= new Item_cond_and(select_lex->having, select_lex->where)))
+ return;
+ if (!(substitution= new Item_func_if(cond, substitution,
+ new Item_null())))
+ return;
+ }
+ }
}
-double Item_singleval_subselect::val ()
+void Item_singlerow_subselect::store(uint i, Item *item)
{
- if (engine->exec())
+ row[i]->store(item);
+}
+
+enum Item_result Item_singlerow_subselect::result_type() const
+{
+ return engine->type();
+}
+
+void Item_singlerow_subselect::fix_length_and_dec()
+{
+ if ((max_columns= engine->cols()) == 1)
+ {
+ engine->fix_length_and_dec(row= &value);
+ if (!(value= Item_cache::get_cache(engine->type())))
+ return;
+ }
+ else
+ {
+ THD *thd= current_thd;
+ if (!(row= (Item_cache**)thd->alloc(sizeof(Item_cache*)*max_columns)))
+ return;
+ engine->fix_length_and_dec(row);
+ value= *row;
+ }
+ maybe_null= engine->may_be_null();
+}
+
+uint Item_singlerow_subselect::cols()
+{
+ return engine->cols();
+}
+
+bool Item_singlerow_subselect::check_cols(uint c)
+{
+ if (c != engine->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), c);
+ return 1;
+ }
+ return 0;
+}
+
+bool Item_singlerow_subselect::null_inside()
+{
+ for (uint i= 0; i < max_columns ; i++)
+ {
+ if (row[i]->null_value)
+ return 1;
+ }
+ return 0;
+}
+
+void Item_singlerow_subselect::bring_value()
+{
+ engine->exec();
+}
+
+double Item_singlerow_subselect::val ()
+{
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val();
+ }
+ else
{
reset();
return 0;
}
- return real_value;
}
-longlong Item_singleval_subselect::val_int ()
+longlong Item_singlerow_subselect::val_int ()
{
- if (engine->exec())
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_int();
+ }
+ else
{
reset();
return 0;
}
- return int_value;
}
-String *Item_singleval_subselect::val_str (String *str)
+String *Item_singlerow_subselect::val_str (String *str)
{
- if (engine->exec() || null_value)
+ if (!engine->exec() && !value->null_value)
+ {
+ null_value= 0;
+ return value->val_str(str);
+ }
+ else
{
reset();
return 0;
}
- return &string_value;
}
Item_exists_subselect::Item_exists_subselect(THD *thd,
@@ -213,7 +332,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
left_expr= left_exp;
func= f;
init(thd, select_lex, new select_exists_subselect(this));
- max_columns= UINT_MAX;
+ max_columns= 1;
reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
@@ -223,8 +342,9 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void Item_exists_subselect::fix_length_and_dec()
{
- decimals=0;
+ decimals= 0;
max_length= 1;
+ max_columns= engine->cols();
}
double Item_exists_subselect::val ()
@@ -313,42 +433,44 @@ Item_allany_subselect::Item_allany_subselect(Item_allany_subselect *item):
func= item->func;
}
-void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
+void Item_in_subselect::single_value_transformer(THD *thd,
+ st_select_lex_unit *unit,
Item *left_expr,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
- if (select_lex->master_unit()->global_parameters->select_limit !=
- HA_POS_ERROR)
+ if (unit->global_parameters->select_limit != HA_POS_ERROR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"LIMIT & IN/ALL/ANY/SOME subquery");
DBUG_VOID_RETURN;
}
+ // no sense in ORDER BY without LIMIT
+ unit->global_parameters->order_list.empty();
+
Item_in_optimizer *optimizer;
substitution= optimizer= new Item_in_optimizer(left_expr, this);
if (!optimizer)
- {
- current_thd->fatal_error= 1;
DBUG_VOID_RETURN;
- }
+
/*
As far as Item_ref_in_optimizer do not substitude itself on fix_fields
we can use same item for all selects.
*/
- Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>",
- (char*)"<left expr>");
- select_lex->master_unit()->dependent= 1;
- for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
+ Item *expr= new Item_ref((Item**)optimizer->get_cache(),
+ (char *)"<no matter>",
+ (char*)"<left expr>");
+ unit->dependent= 1;
+ for (SELECT_LEX * sl= unit->first_select(); sl; sl= sl->next_select())
{
- if (select_lex->select_limit != HA_POS_ERROR)
+ if (sl->select_limit != HA_POS_ERROR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"LIMIT & IN/ALL/ANY/SOME subquery");
DBUG_VOID_RETURN;
}
- select_lex->dependent= 1;
+ sl->dependent= 1;
Item *item;
if (sl->item_list.elements > 1)
{
@@ -358,24 +480,16 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
item= (Item*) sl->item_list.pop();
- if (sl->having || sl->with_sum_func || sl->group_list.first ||
- sl->order_list.first)
+ sl->order_list.empty(); // no sense in ORDER BY without LIMIT
+
+ if (sl->having || sl->with_sum_func || sl->group_list.first)
{
sl->item_list.push_back(item);
item= (*func)(expr, new Item_ref_null_helper(this,
sl->item_list.head_ref(),
(char *)"<no matter>",
(char*)"<result>"));
- if (sl->having || sl->with_sum_func || sl->group_list.first)
- if (sl->having)
- sl->having= new Item_cond_and(sl->having, item);
- else
- sl->having= item;
- else
- if (sl->where)
- sl->where= new Item_cond_and(sl->having, item);
- else
- sl->where= item;
+ sl->having= and_items(sl->having, item);
}
else
{
@@ -386,10 +500,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
item= (*func)(expr, new Item_asterisk_remover(this, item,
(char *)"<no matter>",
(char*)"<result>"));
- if (sl->where)
- sl->where= new Item_cond_and(sl->where, item);
- else
- sl->where= item;
+ sl->where= and_items(sl->where, item);
}
else
{
@@ -399,7 +510,7 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
my_error(ER_NO_TABLES_USED, MYF(0));
DBUG_VOID_RETURN;
}
- if (select_lex->next_select())
+ if (unit->first_select()->next_select())
{
/*
It is in union => we should perform it.
@@ -416,7 +527,6 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
item= (*func)(left_expr, item);
substitution= item;
have_to_be_excluded= 1;
- THD *thd= current_thd;
if (thd->lex.describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
@@ -431,15 +541,91 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
DBUG_VOID_RETURN;
}
-void Item_in_subselect::select_transformer(st_select_lex *select_lex)
+void Item_in_subselect::row_value_transformer(THD *thd,
+ st_select_lex_unit *unit,
+ Item *left_expr)
{
- single_value_transformer(select_lex, left_expr,
- &Item_bool_func2::eq_creator);
+ DBUG_ENTER("Item_in_subselect::row_value_transformer");
+ if (unit->global_parameters->select_limit !=
+ HA_POS_ERROR)
+ {
+ /*
+ Because we do the following (not exactly, following is just explenation)
+ transformation
+ SELECT * from t1 WHERE t1.a IN (SELECT t2.a FROM t2)
+ ->
+ SELECT * from t1 WHERE EXISTS(SELECT 1 FROM t2 t1.a = t2.a LIMIT 1)
+
+ it's impossible to support limit in the sub select.
+ */
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+ // no sense in ORDER BY without LIMIT
+ unit->global_parameters->order_list.empty();
+
+ Item_in_optimizer *optimizer;
+ substitution= optimizer= new Item_in_optimizer(left_expr, this);
+ if (!optimizer)
+ DBUG_VOID_RETURN;
+
+ unit->dependent= 1;
+ uint n= left_expr->cols();
+ if (optimizer->preallocate_row() || (*optimizer->get_cache())->allocate(n))
+ DBUG_VOID_RETURN;
+ for (SELECT_LEX * sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->select_limit != HA_POS_ERROR)
+ {
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0),
+ "LIMIT & IN/ALL/ANY/SOME subquery");
+ DBUG_VOID_RETURN;
+ }
+ sl->order_list.empty(); // no sense in ORDER BY without LIMIT
+
+ sl->dependent= 1;
+
+ Item *item= 0;
+ List_iterator_fast<Item> li(sl->item_list);
+ for (uint i= 0; i < n; i++)
+ {
+ Item *func=
+ new Item_ref_on_list_position(this, sl->item_list, i,
+ (char *) "<no matter>",
+ (char *) "<list ref>");
+ func=
+ Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())->
+ addr(i),
+ (char *)"<no matter>",
+ (char *)"<left expr>"),
+ func);
+ item= and_items(item, func);
+ }
+
+ if (sl->having || sl->with_sum_func || sl->group_list.first ||
+ !sl->table_list.elements)
+ sl->having= and_items(sl->having, item);
+ else
+ sl->where= and_items(sl->where, item);
+ }
+ DBUG_VOID_RETURN;
}
-void Item_allany_subselect::select_transformer(st_select_lex *select_lex)
+
+void Item_in_subselect::select_transformer(THD *thd, st_select_lex_unit *unit)
{
- single_value_transformer(select_lex, left_expr, func);
+ if (left_expr->cols() == 1)
+ single_value_transformer(thd, unit, left_expr,
+ &Item_bool_func2::eq_creator);
+ else
+ row_value_transformer(thd, unit, left_expr);
+}
+
+void Item_allany_subselect::select_transformer(THD *thd,
+ st_select_lex_unit *unit)
+{
+ single_value_transformer(thd, unit, left_expr, func);
}
subselect_single_select_engine::subselect_single_select_engine(THD *thd,
@@ -476,7 +662,7 @@ subselect_union_engine::subselect_union_engine(THD *thd,
subselect_engine(thd, item, result)
{
unit= u;
- if( !result)
+ if (!result)
{
//out of memory
thd->fatal_error= 1;
@@ -492,13 +678,13 @@ int subselect_single_select_engine::prepare()
prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select;
thd->lex.current_select= select_lex;
- if(join->prepare((TABLE_LIST*) select_lex->table_list.first,
- select_lex->where,
- (ORDER*) select_lex->order_list.first,
- (ORDER*) select_lex->group_list.first,
- select_lex->having,
- (ORDER*) 0, select_lex,
- select_lex->master_unit(), 0))
+ if (join->prepare((TABLE_LIST*) select_lex->table_list.first,
+ select_lex->where,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) 0, select_lex,
+ select_lex->master_unit(), 0))
return 1;
thd->lex.current_select= save_select;
return 0;
@@ -509,31 +695,82 @@ int subselect_union_engine::prepare()
return unit->prepare(thd, result);
}
-void subselect_single_select_engine::fix_length_and_dec()
+static Item_result set_row(SELECT_LEX *select_lex, Item * item,
+ Item_cache **row, bool *maybe_null)
{
+ Item_result res_type= STRING_RESULT;
+ Item *sel_item;
List_iterator_fast<Item> li(select_lex->item_list);
- Item *sel_item= li++;
- item->max_length= sel_item->max_length;
- res_type= sel_item->result_type();
- item->decimals= sel_item->decimals;
+ for (uint i= 0; (sel_item= li++); i++)
+ {
+ item->max_length= sel_item->max_length;
+ res_type= sel_item->result_type();
+ item->decimals= sel_item->decimals;
+ *maybe_null= sel_item->maybe_null;
+ if (row)
+ {
+ if (!(row[i]= Item_cache::get_cache(res_type)))
+ return STRING_RESULT; // we should return something
+ row[i]->set_len_n_dec(sel_item->max_length, sel_item->decimals);
+ }
+ }
+ if (select_lex->item_list.elements > 1)
+ res_type= ROW_RESULT;
+ return res_type;
}
-void subselect_union_engine::fix_length_and_dec()
+void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
- uint32 mlen= 0, len;
- Item *sel_item= 0;
- for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ DBUG_ASSERT(row || select_lex->item_list.elements==1);
+ res_type= set_row(select_lex, item, row, &maybe_null);
+ if (cols() != 1)
+ maybe_null= 0;
+}
+
+void subselect_union_engine::fix_length_and_dec(Item_cache **row)
+{
+ DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
+
+ if (unit->first_select()->item_list.elements == 1)
{
- List_iterator_fast<Item> li(sl->item_list);
- Item *s_item= li++;
- if ((len= s_item->max_length))
- mlen= len;
- if (!sel_item)
- sel_item= s_item;
+ uint32 mlen= 0, len;
+ Item *sel_item= 0;
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ List_iterator_fast<Item> li(sl->item_list);
+ Item *s_item= li++;
+ if ((len= s_item->max_length) > mlen)
+ mlen= len;
+ if (!sel_item)
+ sel_item= s_item;
+ maybe_null= s_item->maybe_null;
+ }
+ item->max_length= mlen;
+ res_type= sel_item->result_type();
+ item->decimals= sel_item->decimals;
+ if (row)
+ {
+ if (!(row[0]= Item_cache::get_cache(res_type)))
+ return;
+ row[0]->set_len_n_dec(mlen, sel_item->decimals);
+ }
+ }
+ else
+ {
+ SELECT_LEX *sl= unit->first_select();
+ bool fake= 0;
+ res_type= set_row(sl, item, row, &fake);
+ for (sl= sl->next_select(); sl; sl->next_select())
+ {
+ List_iterator_fast<Item> li(sl->item_list);
+ Item *sel_item;
+ for (uint i= 0; (sel_item= li++); i++)
+ {
+ if (sel_item->max_length > row[i]->max_length)
+ row[i]->max_length= sel_item->max_length;
+ }
+ }
}
- item->max_length= mlen;
- res_type= sel_item->result_type();
- item->decimals= sel_item->decimals;
}
int subselect_single_select_engine::exec()
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 0e6f939803d..cf7f612224a 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -71,7 +71,7 @@ public:
{
null_value= 1;
}
- virtual void select_transformer(st_select_lex *select_lex);
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; }
enum Type type() const;
@@ -86,51 +86,43 @@ public:
bool check_loop(uint id);
friend class select_subselect;
+ friend class Item_in_optimizer;
};
/* single value subselect */
-class Item_singleval_subselect :public Item_subselect
+class Item_cache;
+class Item_singlerow_subselect :public Item_subselect
{
protected:
- longlong int_value; /* Here stored integer value of this item */
- double real_value; /* Here stored real value of this item */
- /*
- Here stored string value of this item.
- (str_value used only as temporary buffer, because it can be changed
- by Item::save_field)
- */
- String string_value;
- enum Item_result res_type; /* type of results */
-
+ Item_cache *value, **row;
public:
- Item_singleval_subselect(THD *thd, st_select_lex *select_lex);
- Item_singleval_subselect(Item_singleval_subselect *item):
+ Item_singlerow_subselect(THD *thd, st_select_lex *select_lex);
+ Item_singlerow_subselect(Item_singlerow_subselect *item):
Item_subselect(item)
{
- int_value= item->int_value;
- real_value= item->real_value;
- string_value.set(item->string_value, 0, item->string_value.length());
+ value= item->value;
max_length= item->max_length;
decimals= item->decimals;
- res_type= item->res_type;
- }
- virtual void reset()
- {
- null_value= 1;
- int_value= 0;
- real_value= 0;
- max_length= 4;
- res_type= STRING_RESULT;
}
- double val ();
+ void reset();
+ void select_transformer(THD *thd, st_select_lex_unit *unit);
+ void store(uint i, Item* item);
+ double val();
longlong val_int ();
String *val_str (String *);
- Item *new_item() { return new Item_singleval_subselect(this); }
- enum Item_result result_type() const { return res_type; }
+ Item *new_item() { return new Item_singlerow_subselect(this); }
+ enum Item_result result_type() const;
void fix_length_and_dec();
- friend class select_singleval_subselect;
+ uint cols();
+ Item* el(uint i) { return (Item*)row[i]; }
+ Item** addr(uint i) { return (Item**)row + i; }
+ bool check_cols(uint c);
+ bool null_inside();
+ void bring_value();
+
+ friend class select_singlerow_subselect;
};
/* exists subselect */
@@ -149,7 +141,7 @@ public:
}
Item_exists_subselect(): Item_subselect() {}
- virtual void reset()
+ void reset()
{
value= 0;
}
@@ -181,9 +173,11 @@ public:
null_value= 0;
was_null= 0;
}
- virtual void select_transformer(st_select_lex *select_lex);
- void single_value_transformer(st_select_lex *select_lex,
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
+ void single_value_transformer(THD *thd, st_select_lex_unit *unit,
Item *left_expr, compare_func_creator func);
+ void row_value_transformer(THD *thd, st_select_lex_unit *unit,
+ Item *left_expr);
longlong val_int();
double val();
String *val_str(String*);
@@ -202,22 +196,18 @@ public:
Item_allany_subselect(THD *thd, Item * left_expr, compare_func_creator f,
st_select_lex *select_lex);
Item_allany_subselect(Item_allany_subselect *item);
- virtual void select_transformer(st_select_lex *select_lex);
+ virtual void select_transformer(THD *thd, st_select_lex_unit *unit);
};
-class subselect_engine
+class subselect_engine: public Sql_alloc
{
protected:
select_subselect *result; /* results storage class */
THD *thd; /* pointer to current THD */
Item_subselect *item; /* item, that use this engine */
enum Item_result res_type; /* type of results */
+ bool maybe_null; /* may be null (first item in select) */
public:
- static void *operator new(size_t size)
- {
- return (void*) sql_alloc((uint) size);
- }
- static void operator delete(void *ptr, size_t size) {}
subselect_engine(THD *thd, Item_subselect *si, select_subselect *res)
{
@@ -225,16 +215,19 @@ public:
item= si;
this->thd= thd;
res_type= STRING_RESULT;
+ maybe_null= 0;
}
+ virtual ~subselect_engine() {}; // to satisfy compiler
virtual int prepare()= 0;
- virtual void fix_length_and_dec()= 0;
+ virtual void fix_length_and_dec(Item_cache** row)= 0;
virtual int exec()= 0;
virtual uint cols()= 0; /* return number of columnss in select */
virtual bool depended()= 0; /* depended from outer select */
enum Item_result type() { return res_type; }
virtual bool check_loop(uint id)= 0;
virtual void exclude()= 0;
+ bool may_be_null() { return maybe_null; };
};
class subselect_single_select_engine: public subselect_engine
@@ -249,7 +242,7 @@ public:
select_subselect *result,
Item_subselect *item);
int prepare();
- void fix_length_and_dec();
+ void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
bool depended();
@@ -266,7 +259,7 @@ public:
select_subselect *result,
Item_subselect *item);
int prepare();
- void fix_length_and_dec();
+ void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
bool depended();
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 89918dafc9e..8f98fa511a0 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -736,7 +736,9 @@ int Query_log_event::write_data(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+ :Log_event(thd_arg, !thd_arg->lex.tmp_table_used ?
+ 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
+ data_buf(0), query(query_arg),
db(thd_arg->db), q_len((uint32) query_length),
error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
thread_id(thd_arg->thread_id)
@@ -818,6 +820,8 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
*end++=';';
*end++='\n';
my_fwrite(file, (byte*) buff, (uint) (end-buff),MYF(MY_NABP | MY_WME));
+ if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
+ fprintf(file,"SET @@session.pseudo_thread_id=%lu;\n",(ulong)thread_id);
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
fprintf(file, ";\n");
}
@@ -853,7 +857,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
thd->query_error= 0; // clear error
thd->clear_error();
- thd->slave_proxy_id = thread_id; // for temp tables
+ thd->variables.pseudo_thread_id= thread_id; // for temp tables
/*
Sanity check to make sure the master did not get a really bad
@@ -1485,7 +1489,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
ex.skip_lines = skip_lines;
List<Item> field_list;
set_fields(field_list);
- thd->slave_proxy_id = thd->thread_id;
+ thd->variables.pseudo_thread_id= thd->thread_id;
if (net)
{
// mysql_load will use thd->net to read the file
diff --git a/sql/log_event.h b/sql/log_event.h
index c4f93c7a9b6..ec3b4819e74 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -212,8 +212,10 @@ struct sql_ex_info
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
-#define LOG_EVENT_TIME_F 0x1
-#define LOG_EVENT_FORCED_ROTATE_F 0x2
+#define LOG_EVENT_TIME_F 0x1
+#define LOG_EVENT_FORCED_ROTATE_F 0x2
+#define LOG_EVENT_THREAD_SPECIFIC_F 0x4 /* query depends on thread
+ (for example: TEMPORARY TABLE) */
enum Log_event_type
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 3d5adf24e03..fa9514c63b7 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -423,6 +423,9 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
bool simple_alter=0);
+int mysql_create_like_table(THD *thd, TABLE_LIST *table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *src_table);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
@@ -464,7 +467,7 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
extern const Field *not_found_field;
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- bool report_error);
+ TABLE_LIST **where, bool report_error);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 13b5d52a343..c2dfc9d1935 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -182,7 +182,6 @@ static char szPipeName [ 257 ];
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
-static uint handler_count;
static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
@@ -1902,6 +1901,7 @@ int main(int argc, char **argv)
set_options();
get_options(argc,argv);
+ max_system_variables.pseudo_thread_id= (ulong)~0;
if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
strcat(server_version,"-log");
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index b917c91ce15..93bae6f444d 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -431,7 +431,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
if (ret_error == ERROR_ACCESS_DENIED)
{
printf("Install/Remove of the Service Denied!\n");
- if(!is_super_user())
+ if (!is_super_user())
printf("That operation should be made by an user with Administrator privileges!\n");
}
else
@@ -530,13 +530,13 @@ BOOL NTService::is_super_user()
UINT x;
BOOL ret_value=FALSE;
- if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,&hAccessToken ))
{
- if(GetLastError() != ERROR_NO_TOKEN)
- return FALSE;
+ if (GetLastError() != ERROR_NO_TOKEN)
+ return FALSE;
- if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
- return FALSE;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken))
+ return FALSE;
}
ret_value= GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
@@ -544,21 +544,21 @@ BOOL NTService::is_super_user()
CloseHandle(hAccessToken);
- if(!ret_value )
- return FALSE;
+ if (!ret_value )
+ return FALSE;
- if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
- SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS,
- 0, 0, 0, 0, 0, 0,
- &psidAdministrators))
- return FALSE;
+ if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &psidAdministrators))
+ return FALSE;
ret_value = FALSE;
- for(x=0;x<ptgGroups->GroupCount;x++)
+ for (x=0;x<ptgGroups->GroupCount;x++)
{
- if( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
+ if ( EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
{
ret_value = TRUE;
break;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index b117b6a5ea1..887ce6c561a 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2162,12 +2162,13 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
tmp=1; // Max one record
else
{
- if(tmp_min_flag & GEOM_FLAG)
+ if (tmp_min_flag & GEOM_FLAG)
{
- tmp=param->table->file->
- records_in_range((int) keynr,(byte*)(param->min_key + 1),
- min_key_length, (ha_rkey_function)(tmp_min_flag ^ GEOM_FLAG),
- (byte *)NullS,0,HA_READ_KEY_EXACT);
+ tmp= param->table->file->
+ records_in_range((int) keynr, (byte*)(param->min_key + 1),
+ min_key_length,
+ (ha_rkey_function)(tmp_min_flag ^ GEOM_FLAG),
+ (byte *)NullS, 0, HA_READ_KEY_EXACT);
}
else
{
diff --git a/sql/password.c b/sql/password.c
index 9fd3757106d..da7a499ba09 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -573,7 +573,7 @@ void get_hash_and_password(ulong* salt, uint8 pversion, char* hash, unsigned cha
while (salt<salt_end) /* Iterate over these elements*/
{
val=*salt;
- for(t=3;t>=0;t--)
+ for (t=3;t>=0;t--)
{
bp[t]=val%256;
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 9d7dc66b452..d7cf9d39b5c 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -616,7 +616,7 @@ bool Protocol_simple::store_null()
field_pos++;
#endif
char buff[1];
- buff[0]= 251;
+ buff[0]= (char)251;
return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
}
@@ -774,13 +774,27 @@ bool Protocol_simple::store_time(TIME *tm)
/****************************************************************************
Functions to handle the binary protocol used with prepared statements
+
+ Data format:
+
+ [ok:1] <-- reserved ok packet
+ [null_field:(field_count+7+2)/8] <-- reserved to send null data. The size is
+ calculated using:
+ bit_fields= (field_count+7+2)/8;
+ 2 bits are reserved
+ [[length]data] <-- data field (the length applies only for
+ string/binary/time/timestamp fields and
+ rest of them are not sent as they have
+ the default length that client understands
+ based on the field type
+ [..]..[[length]data] <-- data
****************************************************************************/
bool Protocol_prep::prepare_for_send(List<Item> *item_list)
{
- field_count=item_list->elements;
- bit_fields= (field_count+3)/8;
- if (packet->alloc(bit_fields))
+ field_count= item_list->elements;
+ bit_fields= (field_count+9)/8;
+ if (packet->alloc(bit_fields+1))
return 1;
/* prepare_for_resend will be called after this one */
return 0;
@@ -789,9 +803,8 @@ bool Protocol_prep::prepare_for_send(List<Item> *item_list)
void Protocol_prep::prepare_for_resend()
{
- packet->length(bit_fields);
- bzero((char*) packet->ptr()+1, bit_fields-1);
- packet[0]=1; // Marker for ok packet
+ packet->length(bit_fields+1);
+ bzero((char*) packet->ptr(), 1+bit_fields);
field_pos=0;
}
@@ -813,7 +826,7 @@ bool Protocol_prep::store(const char *from,uint length)
bool Protocol_prep::store_null()
{
- uint offset=(field_pos+2)/8, bit= (1 << ((field_pos+2) & 7));
+ uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
/* Room for this as it's allocated in prepare_for_send */
char *to= (char*) packet->ptr()+offset;
*to= (char) ((uchar) *to | (uchar) bit);
@@ -839,7 +852,8 @@ bool Protocol_prep::store_short(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
- field_types[field_pos] == MYSQL_TYPE_SHORT);
+ field_types[field_pos] == MYSQL_TYPE_SHORT ||
+ field_types[field_pos] == MYSQL_TYPE_YEAR);
#endif
field_pos++;
char *to= packet->prep_append(2, PACKET_BUFFET_EXTRA_ALLOC);
@@ -936,11 +950,11 @@ bool Protocol_prep::store(TIME *tm)
pos= buff+1;
int2store(pos, tm->year);
- int2store(pos+2, tm->month);
- int2store(pos+3, tm->day);
- int2store(pos+4, tm->hour);
- int2store(pos+5, tm->minute);
- int2store(pos+6, tm->second);
+ pos[2]= (uchar) tm->month;
+ pos[3]= (uchar) tm->day;
+ pos[4]= (uchar) tm->hour;
+ pos[5]= (uchar) tm->minute;
+ pos[6]= (uchar) tm->second;
int4store(pos+7, tm->second_part);
if (tm->second_part)
length=11;
@@ -973,17 +987,24 @@ bool Protocol_prep::store_time(TIME *tm)
field_pos++;
pos= buff+1;
pos[0]= tm->neg ? 1 : 0;
- int4store(pos+1, tm->day);
- int2store(pos+5, tm->hour);
- int2store(pos+7, tm->minute);
- int2store(pos+9, tm->second);
- int4store(pos+11, tm->second_part);
+ int4store(pos+1, tm->day);
+ pos[5]= (uchar) tm->hour;
+ pos[6]= (uchar) tm->minute;
+ pos[7]= (uchar) tm->second;
+ int4store(pos+8, tm->second_part);
if (tm->second_part)
- length=14;
+ length=11;
else if (tm->hour || tm->minute || tm->second || tm->day)
- length=10;
+ length=8;
else
length=0;
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
}
+
+#if 0
+bool Protocol_prep::send_fields(List<Item> *list, uint flag)
+{
+ return prepare_for_send(list);
+};
+#endif
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 63c77f8de2a..a067bab01d7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -21,6 +21,8 @@
- If the variable is thread specific, add it to 'system_variables' struct.
If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
+ - Don't forget to initialize new fields in global_system_variables and
+ max_system_variables!
- Use one of the 'sys_var... classes from set_var.h or write a specific
one for the variable type.
- Define it in the 'variable definition list' in this file.
@@ -154,6 +156,8 @@ sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
&SV::max_heap_table_size);
+sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id",
+ &SV::pseudo_thread_id);
sys_var_thd_ha_rows sys_max_join_size("max_join_size",
&SV::max_join_size,
fix_max_join_size);
@@ -364,6 +368,7 @@ sys_var *sys_variables[]=
&sys_net_retry_count,
&sys_net_wait_timeout,
&sys_net_write_timeout,
+ &sys_pseudo_thread_id,
&sys_query_cache_size,
#ifdef HAVE_QUERY_CACHE
&sys_query_cache_limit,
@@ -512,6 +517,7 @@ struct show_var_st init_vars[]= {
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"port", (char*) &mysql_port, SHOW_INT},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
+ {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index c70ac9ccf57..a1b506f1ff5 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -7,7 +7,7 @@ dist-hook:
done; \
sleep 1 ; touch $(srcdir)/*/errmsg.sys
$(INSTALL_DATA) $(srcdir)/charsets/README $(distdir)/charsets
- $(INSTALL_DATA) $(srcdir)/charsets/Index $(distdir)/charsets
+ $(INSTALL_DATA) $(srcdir)/charsets/Index.xml $(distdir)/charsets
all: @AVAILABLE_LANGUAGES_ERRORS@
@@ -25,7 +25,7 @@ install-data-local:
done
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/charsets
$(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README
- $(INSTALL_DATA) $(srcdir)/charsets/Index $(DESTDIR)$(pkgdatadir)/charsets/Index
+ $(INSTALL_DATA) $(srcdir)/charsets/Index.xml $(DESTDIR)$(pkgdatadir)/charsets/Index.xml
$(INSTALL_DATA) $(srcdir)/charsets/*.conf $(DESTDIR)$(pkgdatadir)/charsets
fix_errors:
diff --git a/sql/share/charsets/Index b/sql/share/charsets/Index
deleted file mode 100644
index b2d9fe3e2a1..00000000000
--- a/sql/share/charsets/Index
+++ /dev/null
@@ -1,70 +0,0 @@
-# sql/share/charsets/Index
-#
-# This file lists all of the available character sets. Please keep this
-# file sorted by character set number.
-
-
-big5 1
-czech 2
-dec8 3
-dos 4
-german1 5
-hp8 6
-koi8_ru 7
-latin1 8
-latin2 9
-swe7 10
-usa7 11
-ujis 12
-sjis 13
-cp1251 14
-danish 15
-hebrew 16
-tis620 18
-euc_kr 19
-estonia 20
-hungarian 21
-koi8_ukr 22
-# win1251ukr is depreciated. Use cp1251cias, cp1251csas or cp1251bin instead.
-win1251ukr 23
-gb2312 24
-greek 25
-win1250 26
-croat 27
-gbk 28
-# cp1257 is depreciated.
-# Use cp1257ltlvciai, cp1257ltlvcsas, cp1257bin, cp1257ltlvcias instead
-cp1257 29
-latin5 30
-latin1_de 31
-armscii8 32
-utf8 33
-win1250ch 34
-
-ucs2 35
-cp866 36
-keybcs2 37
-
-macce 38
-macroman 39
-
-pclatin2 40
-latvian 41
-latvian1 42
-maccebin 43
-macceciai 44
-maccecias 45
-maccecsas 46
-latin1bin 47
-latin1cias 48
-latin1csas 49
-cp1251bin 50
-cp1251cias 51
-cp1251csas 52
-macromanbin 53
-macromancias 54
-macromanciai 55
-macromancsas 56
-cp1256 57
-
-binary 63
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
new file mode 100644
index 00000000000..9dd8b43f0b4
--- /dev/null
+++ b/sql/share/charsets/Index.xml
@@ -0,0 +1,455 @@
+<?xml version='1.0' encoding="utf-8"?>
+
+<charsets max-id=63>
+
+<description>
+This file lists all of the available character sets.
+To make maintaining easier please:
+ - keep records sorted by collation number.
+ - change charset-list.max-id when adding a new collation.
+</description>
+
+<charset name="big5">
+ <family>Traditional Chinese</family>
+ <alias>big-5</alias>
+ <alias>bigfive</alias>
+ <alias>big-five</alias>
+ <alias>cn-big5</alias>
+ <alias>csbig5</alias>
+ <collation name="big5" id="1" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="latin2">
+ <family>Central European</family>
+ <alias>csisolatin2</alias>
+ <alias>iso-8859-2</alias>
+ <alias>iso-ir-101</alias>
+ <alias>iso_8859-2</alias>
+ <alias>iso_8859-2:1987</alias>
+ <alias>l2</alias>
+ <collation name="czech" id="2" order="Czech" flag="compiled"/>
+ <collation name="latin2" id="9" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="hungarian" id="21" order="Hungarian"/>
+ <collation name="croat" id="27" order="Croatian"/>
+</charset>
+
+<charset name="dec8">
+ <family>Western</family>
+ <collation name="dec8" id="3" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="pclatin1">
+ <family>Western</family>
+ <alias>850</alias>
+ <alias>cp850</alias>
+ <alias>cspc850multilingual</alias>
+ <alias>ibm850</alias>
+ <collation name="dos" id="4" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="latin1">
+ <family>Western</family>
+ <alias>csisolatin1</alias>
+ <alias>csisolatin1</alias>
+ <alias>iso-8859-1</alias>
+ <alias>iso-ir-100</alias>
+ <alias>iso_8859-1</alias>
+ <alias>iso_8859-1:1987</alias>
+ <alias>l1</alias>
+ <alias>latin1</alias>
+ <collation name="german1" id="5" order="German Duden"/>
+ <collation name="latin1" id="8" order="Finnish, Swedish" flag="primary"/>
+ <collation name="danish" id="15" order="Danish"/>
+ <collation name="latin1_de" id="31" order="German DIN" flag="compiled"/>
+ <collation name="latin1_bin" id="47" order="Binary"/>
+ <collation name="latin1_ci_as" id="48">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="latin1_cs_as" id="49">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="hp8">
+ <family>Western</family>
+ <alias>hproman8</alias>
+ <collation name="hp8" id="6" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="koi8_ru">
+ <family>Cyrillic</family>
+ <alias>koi8-ru</alias>
+ <alias>cskoi8r</alias>
+ <collation name="koi8_ru" id="7" order="Russian" flag="primary"/>
+</charset>
+
+<charset name="swe7">
+ <family>Western</family>
+ <alias>iso-646-se</alias>
+ <collation name="swe7" id="10" order="Swedish" flag="primary"/>
+</charset>
+
+<charset name="ascii">
+ <family>Western</family>
+ <alias>us</alias>
+ <alias>us-ascii</alias>
+ <alias>csascii</alias>
+ <alias>iso-ir-6</alias>
+ <alias>iso646-us</alias>
+ <collation name="usa7" id="11" order="Egnlish" flag="primary"/>
+</charset>
+
+<charset name="ujis">
+ <family>Japanese</family>
+ <alias>euc-jp</alias>
+ <collation name="ujis" id="12" order="Japanese" flag="primary"/>
+</charset>
+
+<charset name="sjis">
+ <family>Japanese</family>
+ <alias>s-jis</alias>
+ <alias>shift-jis</alias>
+ <alias>x-sjis</alias>
+ <collation name="sjis" id="13" order="Japanese" flag="primary"/>
+</charset>
+
+<charset name="cp1251">
+ <family>Cyrillic</family>
+ <alias>windows-1251</alias>
+ <alias>ms-cyr</alias>
+ <alias>ms-cyrillic</alias>
+ <collation name="cp1251" id="14" flag="primary">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+ <collation name="win1251ukr" id="23" order="<Depreciated>"/>
+ <collation name="cp1251_bin" id="50" order="Binary"/>
+ <collation name="cp1251_ci_as" id="51">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+ <collation name="cp1251_cs_as" id="52">
+ <order>Belarusian</order>
+ <order>Bulgarian</order>
+ <order>Macedonian</order>
+ <order>Russian</order>
+ <order>Serbian</order>
+ <order>Mongolian</order>
+ <order>Ukrainian</order>
+ </collation>
+</charset>
+
+<charset name="hebrew">
+ <family>Hebrew</family>
+ <alias>csisolatinhebrew</alias>
+ <alias>iso-8859-8</alias>
+ <alias>iso-ir-138</alias>
+ <collation name="hebrew" id="16" order="Hebrew" flag="primary"/>
+</charset>
+
+<charset name="tis620">
+ <family>Thai</family>
+ <alias>tis-620</alias>
+ <collation name="tis620" id="18" order="Thai" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="euc_kr">
+ <family>Korean</family>
+ <alias>euckr</alias>
+ <alias>euc-kr</alias>
+ <collation name="euc_kr" id="19" order="Korean" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="latin7">
+ <family>Baltic</family>
+ <alias>BalticRim</alias>
+ <alias>iso-8859-13</alias>
+ <alias>l7</alias>
+ <collation name="estonia" id="20" order="Estonian" flag="primary"/>
+ <collation name="latvian" id="41" order="Latvian"/>
+ <collation name="latvian1" id="42" order="Latvian"/>
+</charset>
+
+<charset name="koi8_ukr">
+ <family>Cyrillic</family>
+ <alias>koi8-u</alias>
+ <collation name="koi8_ukr" id="22" order="Ukranian" flag="primary"/>
+</charset>
+
+<charset name="gb2312">
+ <family>Simplified Chinese</family>
+ <alias>chinese</alias>
+ <alias>iso-ir-58</alias>
+ <collation name="gb2312" id="24" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="greek">
+ <family>Greek</family>
+ <alias>csisolatingreek</alias>
+ <alias>ecma-118</alias>
+ <alias>greek8</alias>
+ <alias>iso-8859-7</alias>
+ <alias>iso-ir-126</alias>
+ <collation name="greek" id="25" order="Greek" flag="primary"/>
+</charset>
+
+<charset name="cp1250">
+ <family>Central European</family>
+ <alias>ms-ce</alias>
+ <alias>windows-1250</alias>
+ <collation name="win1250" id="26" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="win1250ch" id="34" order="Czech"/>
+</charset>
+
+<charset name="gbk">
+ <family>East Asian</family>
+ <alias>cp936</alias>
+ <collation name="gbk" id="28" order="Chinese" flag="primary" flag="compiled"/>
+</charset>
+
+<charset name="cp1257">
+ <family>Baltic</family>
+ <alias>WinBaltRim</alias>
+ <alias>windows-1257</alias>
+ <collation name="cp1257" id="29" order="<Depreciated>"/>
+ <collation name="cp1257_bin" id="58" order="Binary"/>
+ <collation name="cp1257_ci_ai" id="59" flag="primary">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+ <collation name="cp1257_ci_as" id="60">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+ <collation name="cp1257_cs_as" id="61">
+ <order>Latvian</order>
+ <order>Lithuanian</order>
+ </collation>
+</charset>
+
+<charset name="latin5">
+ <family>South Asian</family>
+ <alias>csisolatin5</alias>
+ <alias>iso-8859-9</alias>
+ <alias>iso-ir-148</alias>
+ <alias>l5</alias>
+ <alias>latin5</alias>
+ <alias>turkish</alias>
+ <collation name="latin5" id="30" order="Turkish" flag="primary"/>
+</charset>
+
+<charset name="armscii8">
+ <family>South Asian</family>
+ <alias>armscii-8</alias>
+ <collation name="armscii8" id="32" order="Armenian" flag="primary"/>
+</charset>
+
+<charset name="utf8">
+ <family>Unicode</family>
+ <alias>utf-8</alias>
+ <collation name="utf8" id="33" flag="primary"/>
+</charset>
+
+<charset name="ucs2">
+ <family>Unicode</family>
+ <collation name="ucs2" id="35" flag="primary"/>
+</charset>
+
+<charset name="cp866">
+ <family>Cyrillic</family>
+ <alias>866</alias>
+ <alias>csibm866</alias>
+ <alias>ibm866</alias>
+ <collation name="cp866" id="36" order="Russian" flag="primary"/>
+</charset>
+
+<charset name="keybcs2">
+ <family>Central European</family>
+ <collation name="keybcs2" id="37" order="Czech" flag="primary"/>
+</charset>
+
+<charset name="MacCE">
+ <family>Central European</family>
+ <alias>MacCentralEurope</alias>
+ <collation name="macce" id="38" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_bin" id="43" order="Binary"/>
+ <collation name="macce_ci_ai" id="44">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_ci_as" id="45">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+ <collation name="macce_cs_as" id="46">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+</charset>
+
+<charset name="MacRoman">
+ <family>Western</family>
+ <alias>Mac</alias>
+ <alias>Macintosh</alias>
+ <alias>csmacintosh</alias>
+ <collation name="macroman" id="39" flag="primary">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_bin" id="53" order="Binary"/>
+ <collation name="macroman_ci_as" id="54">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_ci_ai" id="55">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+ <collation name="macroman_cs_as" id="56">
+ <order>Dutch</order>
+ <order>English</order>
+ <order>French</order>
+ <order>German Duden</order>
+ <order>Italian</order>
+ <order>Latin</order>
+ <order>Pogtuguese</order>
+ <order>Spanish</order>
+ </collation>
+</charset>
+
+<charset name="pclatin2">
+ <family>Central European</family>
+ <alias>852</alias>
+ <alias>cp852</alias>
+ <alias>ibm852</alias>
+ <collation name="pclatin2" id="40" flag="primary">
+ <order>Hungarian</order>
+ <order>Polish</order>
+ <order>Romanian</order>
+ <order>Croatian</order>
+ <order>Slovak</order>
+ <order>Slovenian</order>
+ <order>Sorbian</order>
+ </collation>
+</charset>
+
+<charset name="cp1256">
+ <family>Arabic</family>
+ <alias>ms-arab</alias>
+ <alias>windows-1256</alias>
+ <collation name="cp1256" id="57" order="Arabic" flag="primary"/>
+</charset>
+
+<charset name="binary">
+ <collation name="binary" id="63" order="Binary" flag="primary" flag="compiled"/>
+</charset>
+
+</charsets>
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index c1ee8b12e7f..6c3196bfeba 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -259,3 +259,4 @@ v/*
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 17c1dd76474..dcc016511dd 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -253,3 +253,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index a2ef2b0923d..6091616fc4a 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -261,3 +261,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 66d0996f2d6..465992e63b2 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias",
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 367bda922f3..43eb5de89a5 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -255,3 +255,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 93009f564e6..d7bb19c2876 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 24ee7a99409..765fbd875e2 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -260,3 +260,4 @@
"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.",
"Select %u wurde während der Optimierung reduziert.",
"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden."
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index ffed9111859..8831d4e47b9 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index a597e3870b5..8d6c321d316 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -252,3 +252,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 5fd271f8941..451ad3e058b 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index f339faf5fc4..70ab2d6d42d 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -252,3 +252,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 855f157d3b5..c18c3ed3873 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index d930ec5ab74..9cd99613f52 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -252,3 +252,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 15bc59c39dc..32fe6c30b34 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -252,3 +252,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 95315516cda..4b59a62f991 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -254,3 +254,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 47dc0ed569d..7236bd86652 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 722efe4f83f..0b8bbe1c219 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -254,3 +254,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index ddbb5bdbe5d..2f1eedd207c 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -253,3 +253,4 @@
"Every derived table must have it's own alias"
"Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index c9ab4d8f656..75cfd73f3f0 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -246,3 +246,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 0d6a847a341..de354f234c7 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -258,3 +258,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index cc56e1f6aef..a528c3e6b36 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -251,3 +251,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index b792864b9f4..5473f4e8e42 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -250,3 +250,4 @@
"Every derived table must have it's own alias"
"Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 2b6825adb8a..0b91786d1f3 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -255,3 +255,4 @@
"Every derived table must have it's own alias"
"Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" \ No newline at end of file
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 1e2b9f1c512..5c6be3c221c 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -506,7 +506,7 @@ int GPolygon::get_data_as_text(String *txt) const
for (; n_linear_rings>0; --n_linear_rings)
{
- if(no_data(data, 4))
+ if (no_data(data, 4))
return 1;
uint32 n_points = uint4korr(data);
data += 4;
@@ -593,7 +593,7 @@ int GPolygon::area(double *ar) const
data += (8+8);
}
lr_area=fabs(lr_area)/2;
- if(result==-1) result=lr_area;
+ if (result==-1) result=lr_area;
else result-=lr_area;
}
*ar=fabs(result);
@@ -1344,7 +1344,7 @@ int GGeometryCollection::get_mbr(MBR *mbr) const
data += 4;
for (; n_objects>0; --n_objects)
{
- if(no_data(data, WKB_HEADER_SIZE))
+ if (no_data(data, WKB_HEADER_SIZE))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 87cc0d616a9..08016d2df8c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -554,7 +554,7 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
TABLE *table,**prev;
- int4store(key+key_length,thd->slave_proxy_id);
+ int4store(key+key_length,thd->variables.pseudo_thread_id);
key_length += 4;
prev= &thd->temporary_tables;
@@ -594,7 +594,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
(strmov((table->real_name=strmov(table->table_cache_key=key,
db)+1),
table_name) - table->table_cache_key)+1;
- int4store(key+table->key_length,thd->slave_proxy_id);
+ int4store(key+table->key_length,thd->variables.pseudo_thread_id);
table->key_length += 4;
return 0;
}
@@ -748,7 +748,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
- int4store(key + key_length, thd->slave_proxy_id);
+ int4store(key + key_length, thd->variables.pseudo_thread_id);
for (table=thd->temporary_tables; table ; table=table->next)
{
@@ -762,6 +762,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0);
}
table->query_id=thd->query_id;
+ thd->lex.tmp_table_used= 1;
goto reset;
}
}
@@ -1562,7 +1563,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
+1), table_name)
- tmp_table->table_cache_key)+1;
int4store(tmp_table->table_cache_key + tmp_table->key_length,
- thd->slave_proxy_id);
+ thd->variables.pseudo_thread_id);
tmp_table->key_length += 4;
if (link_in_list)
@@ -1654,6 +1655,7 @@ const Field *not_found_field= (Field*) 0x1;
thd - pointer to current thread structure
item - field item that should be found
tables - tables for scaning
+ where - table where field found will be returned via this parameter
report_error - if FALSE then do not report error if item not found and
return not_found_field;
@@ -1667,7 +1669,7 @@ const Field *not_found_field= (Field*) 0x1;
Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- bool report_error)
+ TABLE_LIST **where, bool report_error)
{
Field *found=0;
const char *db=item->db_name;
@@ -1688,6 +1690,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
grant_option && !thd->master_access,1);
if (find)
{
+ (*where)= tables;
if (find == WRONG_GRANT)
return (Field*) 0;
if (db || !thd->where)
@@ -1707,7 +1710,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (!found_table && report_error)
{
char buff[NAME_LEN*2+1];
- if (db)
+ if (db && db[0])
{
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
@@ -1735,6 +1738,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool allow_rowid= tables && !tables->next; // Only one table
for (; tables ; tables=tables->next)
{
+ if (!tables->table)
+ {
+ if (report_error)
+ my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
+ item->full_name(),thd->where);
+ return (Field*) not_found_field;
+ }
+
Field *field=find_field_in_table(thd,tables->table,name,length,
grant_option &&
!thd->master_access, allow_rowid);
@@ -1742,6 +1753,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
if (field == WRONG_GRANT)
return (Field*) 0;
+ (*where)= tables;
if (found)
{
if (!thd->where) // Returns first found
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index aa0f5824b4e..1cfbbf74da6 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1062,6 +1062,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
for (; tables_used; tables_used=tables_used->next)
{
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
+ if (tables_used->derived)
+ continue;
if (using_transactions &&
tables_used->table->file->has_transactions())
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ef40ebeb273..3ca1f4827ff 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -100,7 +100,7 @@ THD::THD():user_time(0), fatal_error(0),
start_time=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
- slave_proxy_id = 0;
+ variables.pseudo_thread_id= 0;
file_id = 0;
cond_count=0;
warn_id= 0;
@@ -917,10 +917,10 @@ select_subselect::select_subselect(Item_subselect *item)
this->item=item;
}
-bool select_singleval_subselect::send_data(List<Item> &items)
+bool select_singlerow_subselect::send_data(List<Item> &items)
{
- DBUG_ENTER("select_singleval_subselect::send_data");
- Item_singleval_subselect *it= (Item_singleval_subselect *)item;
+ DBUG_ENTER("select_singlerow_subselect::send_data");
+ Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
if (it->assigned())
{
my_message(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0));
@@ -932,32 +932,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
DBUG_RETURN(0);
}
List_iterator_fast<Item> li(items);
- Item *val_item= li++; // Only one (single value subselect)
- /*
- Following val() call have to be first, because function AVG() & STD()
- calculate value on it & determinate "is it NULL?".
- */
- it->real_value= val_item->val_result();
- if ((it->null_value= val_item->null_value))
- {
- it->reset();
- }
- else
- {
- it->max_length= val_item->max_length;
- it->decimals= val_item->decimals;
- it->set_charset(val_item->charset());
- it->int_value= val_item->val_int_result();
- String *s= val_item->str_result(&it->string_value);
- if (s != &it->string_value)
- {
- it->string_value.set(*s, 0, s->length());
- }
- // TODO: remove when correct charset handling appeared for Item
- it->str_value.set(*s, 0, s->length()); // store charset
-
- it->res_type= val_item->result_type();
- }
+ Item *val_item;
+ for (uint i= 0; (val_item= li++); i++)
+ it->store(i, val_item);
it->assigned(1);
DBUG_RETURN(0);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7cf822585c9..a053db72e64 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -370,6 +370,12 @@ struct system_variables
ulong tmp_table_size;
ulong tx_isolation;
+ /*
+ In slave thread we need to know in behalf of which
+ thread the query is being run to replicate temp tables properly
+ */
+ ulong pseudo_thread_id;
+
my_bool log_warnings;
my_bool low_priority_updates;
@@ -525,11 +531,6 @@ public:
each thread that is using LOG_INFO needs to adjust the pointer to it
*/
LOG_INFO* current_linfo;
- /*
- In slave thread we need to know in behalf of which
- thread the query is being run to replicate temp tables properly
- */
- ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m.
my_off_t log_pos;
/* Used by the sys_var class to store temporary values */
@@ -824,10 +825,10 @@ public:
};
/* Single value subselect interface class */
-class select_singleval_subselect :public select_subselect
+class select_singlerow_subselect :public select_subselect
{
public:
- select_singleval_subselect(Item_subselect *item):select_subselect(item){}
+ select_singlerow_subselect(Item_subselect *item):select_subselect(item){}
bool send_data(List<Item> &items);
};
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index f7d845e9e36..1ddaedeb480 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -63,6 +63,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
TMP_TABLE_PARAM tmp_table_param;
bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
DBUG_ENTER("mysql_derived");
+ SELECT_LEX_NODE *save_current_select= lex->current_select;
/*
@@ -111,6 +112,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
}
}
+ lex->current_select= sl;
if (setup_fields(thd,tables,item_list,0,0,1))
{
res=-1;
@@ -119,7 +121,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, is_union && !unit->union_option, 1,
+ (ORDER*) 0,
+ is_union && !unit->union_option, 1,
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
@@ -138,8 +141,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (unit->select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
- SELECT_LEX_NODE *save_current_select= lex->current_select;
- lex->current_select= sl;
if (is_union)
res=mysql_union(thd,lex,derived_result,unit);
else
@@ -149,7 +150,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
- lex->current_select= save_current_select;
if (!res)
{
@@ -168,14 +168,9 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
tables->table_list->table=tables->table; // to fix a problem in EXPLAIN
}
else
- {
- if (is_union)
- unit->exclude();
- else
- sl->exclude();
- }
+ unit->exclude();
t->db=(char *)"";
- t->derived=(SELECT_LEX *)0; // just in case ...
+ t->derived=(SELECT_LEX *)1; // just in case ...
table->file->info(HA_STATUS_VARIABLE);
}
}
@@ -184,6 +179,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (res)
free_tmp_table(thd,table);
exit:
+ lex->current_select= save_current_select;
close_thread_tables(thd);
}
DBUG_RETURN(res);
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 5d12f023842..013101a0ecc 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -96,7 +96,7 @@ int search_functions(MI_INFO *file_leafs, const char *mask,
DBUG_ENTER("search_functions");
int count= 0;
- if(mi_scan_init(file_leafs))
+ if (mi_scan_init(file_leafs))
DBUG_RETURN(-1);
help_leaf leaf;
@@ -191,7 +191,7 @@ int search_categories(THD *thd,
if (!(file_categories= open_help_file(thd,"function_category_name")))
DBUG_RETURN(-1);
- if(mi_scan_init(file_categories))
+ if (mi_scan_init(file_categories))
{
mi_close(file_categories);
DBUG_RETURN(-1);
@@ -393,11 +393,11 @@ int mysqld_help(THD *thd, const char *mask)
description->ptr(), example->ptr())))
goto end;
}
- else if((res= send_header_2(protocol)) ||
- (res= send_variant_2_list(protocol,&function_list,false)) ||
- (search_categories(thd, mask, &categories_list, 0)<0 &&
- (res=1)) ||
- (res= send_variant_2_list(protocol,&categories_list,true)))
+ else if ((res= send_header_2(protocol)) ||
+ (res= send_variant_2_list(protocol,&function_list,false)) ||
+ (search_categories(thd, mask, &categories_list, 0)<0 &&
+ (res=1)) ||
+ (res= send_variant_2_list(protocol,&categories_list,true)))
{
goto end;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index ddbb562bdca..c7595c7ec5c 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -171,6 +171,7 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->slave_thd_opt=0;
lex->sql_command=SQLCOM_END;
lex->safe_to_cache_query= 1;
+ lex->tmp_table_used= 0;
bzero(&lex->mi,sizeof(lex->mi));
return lex;
}
@@ -1036,7 +1037,7 @@ void st_select_lex_node::include_global(st_select_lex_node **plink)
//excluding from global list (internal function)
void st_select_lex_node::fast_exclude()
{
- if(link_prev)
+ if (link_prev)
{
if ((*link_prev= link_next))
link_next->link_prev= link_prev;
@@ -1068,7 +1069,7 @@ void st_select_lex_node::exclude()
void st_select_lex_unit::exclude_level()
{
SELECT_LEX_UNIT *units= 0, **units_last= &units;
- for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl->link_prev && (*sl->link_prev= sl->link_next))
sl->link_next->link_prev= sl->link_prev;
@@ -1142,7 +1143,7 @@ void st_select_lex_node::mark_as_dependent(SELECT_LEX *last)
for (SELECT_LEX_NODE *s= this;
s &&s != last;
s= s->outer_select())
- if( !s->dependent )
+ if ( !s->dependent )
{
// Select is dependent of outer select
s->dependent= 1;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6e5fd6765fb..9b8f4a47515 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -461,6 +461,7 @@ typedef struct st_lex
uint slave_thd_opt;
CHARSET_INFO *charset;
char *help_arg;
+ bool tmp_table_used;
} LEX;
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 6eb4fbcaaf6..1f22073f556 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -62,7 +62,7 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
List_iterator<Item> list_it(select_lex->item_list);
List_iterator<Item> new_it(new_fields);
- while((item=list_it++))
+ while ((item=list_it++))
{
bool not_found=true;
if (item->type()==Item::FIELD_ITEM)
@@ -109,15 +109,15 @@ static int olap_combos(List<Item> old_fields, List<Item> new_fields, Item *item
int num_new_fields)
{
int sl_return = 0;
- if(position == num_new_fields)
+ if (position == num_new_fields)
{
- if(item)
+ if (item)
new_fields.push_front(item);
sl_return = make_new_olap_select(lex, select_lex, new_fields);
}
else
{
- if(item)
+ if (item)
new_fields.push_front(item);
while ((num_fields - num_new_fields >= selection - position) && !sl_return)
{
@@ -170,12 +170,12 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (select_lex->olap == CUBE_TYPE)
{
- for( int i=count-1; i>=0 && !sl_return; i--)
+ for ( int i=count-1; i>=0 && !sl_return; i--)
sl_return=olap_combos(item_list_copy, new_item_list, (Item *)0, lex, select_lex, 0, 0, count, i);
}
else if (select_lex->olap == ROLLUP_TYPE)
{
- for( int i=count-1; i>=0 && !sl_return; i--)
+ for ( int i=count-1; i>=0 && !sl_return; i--)
{
Item *item;
item_list_copy.pop();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 85658a93791..b47ce194a57 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -189,9 +189,9 @@ end:
static int check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count,
- bool do_send_error, char* crypted_scramble,
- bool had_password,uint *cur_priv_version,
- ACL_USER** hint_user)
+ bool simple_connect, bool do_send_error,
+ char* crypted_scramble, bool had_password,
+ uint *cur_priv_version, ACL_USER** hint_user)
{
thd->db=0;
thd->db_length=0;
@@ -222,14 +222,23 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
{
if (do_send_error)
{
- net_printf(thd, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- had_password ? ER(ER_YES) : ER(ER_NO));
- mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
- thd->user,
- thd->host_or_ip,
- had_password ? ER(ER_YES) : ER(ER_NO));
+ /* Old client should get nicer error message if password version is not supported*/
+ if (simple_connect && *hint_user && (*hint_user)->pversion)
+ {
+ net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ }
+ else
+ {
+ net_printf(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host_or_ip,
+ had_password ? ER(ER_YES) : ER(ER_NO));
+ mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
+ thd->user,
+ thd->host_or_ip,
+ had_password ? ER(ER_YES) : ER(ER_NO));
+ }
return(1); // Error already given
}
else
@@ -640,8 +649,9 @@ check_connections(THD *thd)
/* Store information if we used password. passwd will be dammaged */
bool using_password=test(passwd[0]);
/* Check user permissions. If password failure we'll get scramble back */
- if (check_user(thd,COM_CONNECT, user, passwd, db, 1, simple_connect,
- prepared_scramble,using_password,&cur_priv_version,&cached_user)<0)
+ if (check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
+ simple_connect, prepared_scramble, using_password, &cur_priv_version,
+ &cached_user)<0)
{
/* If The client is old we just have to return error */
if (simple_connect)
@@ -681,7 +691,7 @@ check_connections(THD *thd)
}
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
- tmp_db, 1, 1,prepared_scramble,using_password,&cur_priv_version,
+ tmp_db, 1, 0, 1, prepared_scramble, using_password, &cur_priv_version,
&cached_user))
return -1;
}
@@ -1085,7 +1095,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
Do not retry if we already have sent error (result>0)
*/
if (check_user(thd,COM_CHANGE_USER, user, passwd, db, 0, simple_connect,
- prepared_scramble,using_password,&cur_priv_version,&cached_user)<0)
+ simple_connect, prepared_scramble, using_password, &cur_priv_version,
+ &cached_user)<0)
{
/* If The client is old we just have to have auth failure */
if (simple_connect)
@@ -1120,7 +1131,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*)net->read_pos,
- tmp_db, 0, 1,prepared_scramble,using_password,&cur_priv_version,
+ tmp_db, 0, 0, 1, prepared_scramble, using_password, &cur_priv_version,
&cached_user))
goto restore_user;
}
@@ -1469,7 +1480,6 @@ mysql_execute_command(THD *thd)
int res= 0;
LEX *lex= &thd->lex;
TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
- TABLE_LIST *cursor;
SELECT_LEX *select_lex= &lex->select_lex;
SELECT_LEX_UNIT *unit= &lex->unit;
DBUG_ENTER("mysql_execute_command");
@@ -1607,7 +1617,14 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_DO:
- res=mysql_do(thd, *lex->insert_list);
+ if (tables && ((res= check_table_access(thd, SELECT_ACL, tables)) ||
+ (res= open_and_lock_tables(thd,tables))))
+ break;
+
+ fix_tables_pointers(lex->all_selects_list);
+ res= mysql_do(thd, *lex->insert_list);
+ if (thd->net.report_error)
+ res= -1;
break;
case SQLCOM_EMPTY_QUERY:
@@ -1813,7 +1830,6 @@ mysql_execute_command(THD *thd)
}
if (tables->next)
{
- TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given
}
@@ -1840,10 +1856,14 @@ mysql_execute_command(THD *thd)
}
else // regular create
{
- res = mysql_create_table(thd,tables->db ? tables->db : thd->db,
- tables->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,0,0,0); // do logging
+ if (lex->name)
+ res= mysql_create_like_table(thd, tables, &lex->create_info,
+ (Table_ident *)lex->name);
+ else
+ res= mysql_create_table(thd,tables->db ? tables->db : thd->db,
+ tables->real_name, &lex->create_info,
+ lex->create_list,
+ lex->key_list,0,0,0); // do logging
if (!res)
send_ok(thd);
}
@@ -3034,6 +3054,7 @@ mysql_init_query(THD *thd)
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe=0;
lex->derived_tables= false;
+ lex->lock_option=TL_READ;
thd->check_loops_counter= thd->select_number=
lex->select_lex.select_number= 1;
thd->free_list= 0;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 704acc9c1c2..93004ce2937 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -440,10 +440,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
COND *conds)
{
THD *thd= stmt->thd;
- TABLE *table;
DBUG_ENTER("mysql_test_upd_fields");
- if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
+ if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1);
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
@@ -477,13 +476,12 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
COND *conds, ORDER *order, ORDER *group,
Item *having)
{
- TABLE *table;
bool hidden_group_fields;
THD *thd= stmt->thd;
List<Item> all_fields(fields);
DBUG_ENTER("mysql_test_select_fields");
- if (!(table = open_ltable(thd,tables,TL_READ)))
+ if (open_and_lock_tables(thd, tables))
DBUG_RETURN(1);
thd->used_tables=0; // Updated by setup_fields
@@ -512,7 +510,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
sending any info on where clause.
*/
if (send_prep_stmt(stmt, fields.elements) ||
- thd->protocol_prep.send_fields(&fields,0) ||
+ thd->protocol_simple.send_fields(&fields,0) ||
send_item_params(stmt))
DBUG_RETURN(1);
DBUG_RETURN(0);
@@ -626,14 +624,17 @@ static bool parse_prepare_query(PREP_STMT *stmt,
/*
Initialize parameter items in statement
*/
-static bool init_param_items(THD *thd, PREP_STMT *stmt)
+
+static bool init_param_items( PREP_STMT *stmt)
{
+ List<Item> &params= stmt->thd->lex.param_list;
Item_param **to;
+
if (!(stmt->param= to= (Item_param **)
my_malloc(sizeof(Item_param *)*(stmt->param_count+1),
MYF(MY_WME))))
return 1;
- List_iterator<Item> param_iterator(thd->lex.param_list);
+ List_iterator<Item> param_iterator(params);
while ((*(to++) = (Item_param *)param_iterator++));
return 0;
}
@@ -659,29 +660,32 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
DBUG_ENTER("mysql_stmt_prepare");
bzero((char*) &stmt, sizeof(stmt));
- stmt.thd= thd;
+
stmt.stmt_id= ++thd->current_stmt_id;
init_sql_alloc(&stmt.mem_root, 8192, 8192);
+
+ stmt.thd= thd;
+ stmt.thd->mem_root= stmt.mem_root;
- thd->mem_root= stmt.mem_root;
- if (alloc_query(thd, packet, packet_length))
+ if (alloc_query(stmt.thd, packet, packet_length))
goto err;
+
if (parse_prepare_query(&stmt, thd->query, thd->query_length))
goto err;
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
- if (init_param_items(thd, &stmt))
+ if (init_param_items(&stmt))
goto err;
- stmt.mem_root= thd->mem_root;
+ stmt.mem_root= stmt.thd->mem_root;
tree_insert(&thd->prepared_statements, (void *)&stmt, 0, (void *)0);
thd->mem_root= thd_root; // restore main mem_root
DBUG_RETURN(0);
err:
- stmt.mem_root= thd->mem_root;
+ stmt.mem_root= stmt.thd->mem_root;
free_prep_stmt(&stmt, free_free, (void*) 0);
thd->mem_root = thd_root; // restore main mem_root
DBUG_RETURN(1);
@@ -727,9 +731,9 @@ void mysql_stmt_execute(THD *thd, char *packet)
mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things ..
*/
- thd->protocol= &thd->protocol_prep; // Switch to binary protocol
+ stmt->thd->protocol= &thd->protocol_prep; // Switch to binary protocol
mysql_execute_command(stmt->thd);
- thd->protocol= &thd->protocol_simple; // Use normal protocol
+ stmt->thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b6cc68477aa..b57e45a1a52 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1160,7 +1160,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
if (thd->possible_loops)
{
Item *item;
- while(thd->possible_loops->elements)
+ while (thd->possible_loops->elements)
{
item= thd->possible_loops->pop();
if (item->check_loop(thd->check_loops_counter++))
@@ -7540,7 +7540,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table;
char buff[512],*buff_ptr=buff;
- char buff1[512], buff2[512], buff3[512];
+ char buff1[512], buff2[512];
String tmp1(buff1,sizeof(buff1),default_charset_info);
String tmp2(buff2,sizeof(buff2),default_charset_info);
tmp1.length(0);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 41f2ab975f5..c66764d673f 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -841,7 +841,6 @@ int
mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- char buff[256];
Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
@@ -1113,8 +1112,8 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append(" USING BTREE", 12);
// +BAR: send USING only in non-default case: non-spatial rtree
- if((key_info->algorithm == HA_KEY_ALG_RTREE) &&
- !(key_info->flags & HA_SPATIAL))
+ if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
+ !(key_info->flags & HA_SPATIAL))
packet->append(" USING RTREE",12);
packet->append(" (", 2);
@@ -1330,7 +1329,6 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
time_t now= time(0);
while ((thd_info=thread_infos.get()))
{
- char buff[20],*end;
protocol->prepare_for_resend();
protocol->store((ulonglong) thd_info->thread_id);
protocol->store(thd_info->user);
@@ -1365,10 +1363,14 @@ int mysqld_show_charsets(THD *thd, const char *wild)
List<Item> field_list;
CHARSET_INFO **cs;
Protocol *protocol= thd->protocol;
+ char flags[64];
+
DBUG_ENTER("mysqld_show_charsets");
- field_list.push_back(new Item_empty_string("Name",30));
+ field_list.push_back(new Item_empty_string("CS_Name",30));
+ field_list.push_back(new Item_empty_string("COL_Name",30));
field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
+ field_list.push_back(new Item_empty_string("Flags",30));
field_list.push_back(new Item_return_int("strx_maxlen",3, FIELD_TYPE_TINY));
field_list.push_back(new Item_return_int("mb_maxlen",3, FIELD_TYPE_TINY));
@@ -1377,14 +1379,17 @@ int mysqld_show_charsets(THD *thd, const char *wild)
for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
{
- if (!cs[0])
- continue;
- if (!(wild && wild[0] &&
+ if (cs[0] && !(wild && wild[0] &&
wild_case_compare(system_charset_info,cs[0]->name,wild)))
{
protocol->prepare_for_resend();
+ protocol->store(cs[0]->csname);
protocol->store(cs[0]->name);
protocol->store_short((longlong) cs[0]->number);
+ flags[0]='\0';
+ if (cs[0]->state & MY_CS_PRIMARY)
+ strcat(flags,"pri");
+ protocol->store(flags);
protocol->store_tiny((longlong) cs[0]->strxfrm_multiply);
protocol->store_tiny((longlong) cs[0]->mbmaxlen);
if (protocol->write())
@@ -1473,7 +1478,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
end= int10_to_str((long) thd->query_id, buff, 10);
break;
case SHOW_RPL_STATUS:
- end= int10_to_str((long) rpl_status_type[(int)rpl_status], buff, 10);
+ end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
case SHOW_SLAVE_RUNNING:
{
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 51b2386ae62..5b84b86c277 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -254,7 +254,7 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *from, CHARSET
break;
outp:
- if((cnvres=to->wc_mb(to,wc,d,de)) >0 )
+ if ((cnvres=to->wc_mb(to,wc,d,de)) >0 )
{
d+=cnvres;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4848c374932..1f4657fb55f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -210,6 +210,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
wrong_tables.append(String(table->real_name,default_charset_info));
}
}
+ thd->lex.tmp_table_used= tmp_table_deleted;
if (some_tables_deleted || tmp_table_deleted)
{
query_cache_invalidate3(thd, tables, 0);
@@ -418,7 +419,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
it.rewind();
while ((sql_field=it++))
{
- if(!sql_field->charset)
+ if (!sql_field->charset)
sql_field->charset = create_info->table_charset ?
create_info->table_charset :
thd->db_charset? thd->db_charset :
@@ -834,6 +835,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
(void) rm_temporary_table(create_info->db_type, path);
goto end;
}
+ thd->lex.tmp_table_used= 1;
}
if (!tmp_table && !no_log)
{
@@ -1396,6 +1398,127 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
}
+/*
+ Create a table identical to the specified table
+
+ SYNOPSIS
+ mysql_create_like_table()
+ thd Thread object
+ table Table list (one table only)
+ create_info Create info
+ table_ident Src table_ident
+
+ RETURN VALUES
+ 0 ok
+ -1 error
+*/
+
+int mysql_create_like_table(THD* thd, TABLE_LIST* table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *table_ident)
+{
+ TABLE **tmp_table;
+ char src_path[FN_REFLEN], dst_path[FN_REFLEN];
+ char *db= table->db;
+ char *table_name= table->real_name;
+ char *src_db= thd->db;
+ char *src_table= table_ident->table.str;
+ int err;
+
+ DBUG_ENTER("mysql_create_like_table");
+
+ /*
+ Validate the source table
+ */
+ if (table_ident->table.length > NAME_LEN ||
+ (table_ident->table.length &&
+ check_table_name(src_table,table_ident->table.length)) ||
+ table_ident->db.str && check_db_name((src_db= table_ident->db.str)))
+ {
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
+ DBUG_RETURN(-1);
+ }
+
+ if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
+ strxmov(src_path, (*tmp_table)->path, reg_ext, NullS);
+ else
+ {
+ strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table,
+ reg_ext, NullS);
+ if (access(src_path, F_OK))
+ {
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
+ DBUG_RETURN(-1);
+ }
+ }
+
+ /*
+ Validate the destination table
+
+ skip the destination table name checking as this is already
+ validated.
+ */
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (find_temporary_table(thd, db, table_name))
+ goto table_exists;
+ sprintf(dst_path,"%s%s%lx_%lx_%x%s",mysql_tmpdir,tmp_file_prefix,
+ current_pid, thd->thread_id, thd->tmp_table++,reg_ext);
+ create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
+ }
+ else
+ {
+ strxmov(dst_path, mysql_data_home, "/", db, "/", table_name,
+ reg_ext, NullS);
+ if (!access(dst_path, F_OK))
+ goto table_exists;
+ }
+
+ /*
+ Create a new table by copying from source table
+ */
+ if (my_copy(src_path, dst_path, MYF(MY_WME)))
+ DBUG_RETURN(-1);
+
+ /*
+ As mysql_truncate don't work on a new table at this stage of
+ creation, instead create the table directly (for both normal
+ and temporary tables).
+ */
+ *fn_ext(dst_path)= 0;
+ err= ha_create_table(dst_path, create_info, 1);
+
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
+ {
+ (void) rm_temporary_table(create_info->db_type,
+ dst_path); /* purecov: inspected */
+ DBUG_RETURN(-1); /* purecov: inspected */
+ }
+ }
+ else if (err)
+ {
+ (void) quick_rm_table(create_info->db_type, db,
+ table_name); /* purecov: inspected */
+ DBUG_RETURN(-1); /* purecov: inspected */
+ }
+ DBUG_RETURN(0);
+
+table_exists:
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+ sprintf(warn_buff,ER(ER_TABLE_EXISTS_ERROR),table_name);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_EXISTS_ERROR,warn_buff);
+ DBUG_RETURN(0);
+ }
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
+ DBUG_RETURN(-1);
+}
+
+
int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index 3fbeaa753db..758778ecfa8 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -276,6 +276,7 @@ static void display_table_locks (void)
VOID(pthread_mutex_unlock(&lock->mutex));
}
VOID(pthread_mutex_unlock(&THR_LOCK_lock));
+ uint i;
if (!saved_table_locks.elements) goto end;
qsort((gptr) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare);
@@ -283,7 +284,7 @@ static void display_table_locks (void)
puts("\nThread database.table_name Locked/Waiting Lock_type\n");
- for (uint i=0 ; i < saved_table_locks.elements ; i++)
+ for (i=0 ; i < saved_table_locks.elements ; i++)
{
TABLE_LOCK_INFO *dl_ptr=dynamic_element(&saved_table_locks,i,TABLE_LOCK_INFO*);
printf("%-8ld%-28.28s%-22s%s\n",
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 51d43b41833..324befcb59e 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -33,6 +33,7 @@
#endif
#include "mysql_priv.h"
+#include <my_pthread.h>
#ifdef HAVE_DLOPEN
extern "C"
@@ -70,7 +71,7 @@ extern "C"
static bool initialized = 0;
static MEM_ROOT mem;
static HASH udf_hash;
-static pthread_mutex_t THR_LOCK_udf;
+static rw_lock_t THR_LOCK_udf;
static udf_func *add_udf(char *name, Item_result ret, char *dl,
@@ -122,8 +123,8 @@ void udf_init()
if (initialized)
DBUG_VOID_RETURN;
- pthread_mutex_init(&THR_LOCK_udf,MY_MUTEX_INIT_SLOW);
-
+ my_rwlock_init(&THR_LOCK_udf,NULL);
+
init_sql_alloc(&mem, 1024,0);
THD *new_thd = new THD;
if (!new_thd ||
@@ -262,7 +263,7 @@ static void del_udf(udf_func *udf)
void free_udf(udf_func *udf)
{
DBUG_ENTER("free_udf");
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_wrlock(&THR_LOCK_udf);
if (!--udf->usage_count)
{
/*
@@ -274,7 +275,7 @@ void free_udf(udf_func *udf)
if (!find_udf_dl(udf->dl))
dlclose(udf->dlhandle);
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_VOID_RETURN;
}
@@ -287,7 +288,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
DBUG_ENTER("find_udf");
/* TODO: This should be changed to reader locks someday! */
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_rdlock(&THR_LOCK_udf);
if ((udf=(udf_func*) hash_search(&udf_hash,(byte*) name,
length ? length : (uint) strlen(name))))
{
@@ -296,7 +297,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
else if (mark_used)
udf->usage_count++;
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(udf);
}
@@ -375,7 +376,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
DBUG_RETURN(1);
}
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_wrlock(&THR_LOCK_udf);
if ((hash_search(&udf_hash,(byte*) udf->name, udf->name_length)))
{
net_printf(thd, ER_UDF_EXISTS, udf->name);
@@ -438,13 +439,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
del_udf(u_d);
goto err;
}
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(0);
err:
if (new_dl)
dlclose(dl);
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(1);
}
@@ -460,7 +461,7 @@ int mysql_drop_function(THD *thd,const char *udf_name)
send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
DBUG_RETURN(1);
}
- pthread_mutex_lock(&THR_LOCK_udf);
+ rw_wrlock(&THR_LOCK_udf);
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name,
(uint) strlen(udf_name))))
{
@@ -490,10 +491,10 @@ int mysql_drop_function(THD *thd,const char *udf_name)
}
close_thread_tables(thd);
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(0);
err:
- pthread_mutex_unlock(&THR_LOCK_udf);
+ rw_unlock(&THR_LOCK_udf);
DBUG_RETURN(1);
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 10175bfe345..cdd34977e5a 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -279,9 +279,10 @@ int st_select_lex_unit::exec()
}
if (!thd->fatal_error) // Check if EOM
{
- offset_limit_cnt= global_parameters->offset_limit;
- select_limit_cnt= global_parameters->select_limit+
- global_parameters->offset_limit;
+ SELECT_LEX *sl=thd->lex.current_select->master_unit()->first_select();
+ offset_limit_cnt= (sl->braces) ? global_parameters->offset_limit : 0;
+ select_limit_cnt= (sl->braces) ? global_parameters->select_limit+
+ global_parameters->offset_limit : HA_POS_ERROR;
if (select_limit_cnt < global_parameters->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e99f2a3b17c..bcee15c13cf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -587,7 +587,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr
using_list expr_or_default set_expr_or_default
- param_marker singleval_subselect singleval_subselect_init
+ param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init
%type <item_list>
@@ -835,6 +835,7 @@ create:
lex->create_info.options=$2 | $4;
lex->create_info.db_type= (enum db_type) lex->thd->variables.table_type;
lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
+ lex->name=0;
}
create2
{}
@@ -883,7 +884,13 @@ create:
create2:
'(' field_list ')' opt_create_table_options create3 {}
| opt_create_table_options create3 {}
- ;
+ | LIKE table_ident
+ {
+ LEX *lex=Lex;
+ if (!(lex->name= (char *)$2))
+ YYABORT;
+ }
+ ;
create3:
/* empty */ {}
@@ -1669,12 +1676,17 @@ select_init:
'(' SELECT_SYM select_part2 ')'
{
LEX *lex= Lex;
- SELECT_LEX_NODE * sel= lex->current_select;
+ SELECT_LEX * sel= lex->current_select->select_lex();
if (sel->set_braces(1))
{
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
+ if (sel->linkage == UNION_TYPE && !sel->master_unit()->first_select()->braces)
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
/* select in braces, can't contain global parameters */
sel->master_unit()->global_parameters=
sel->master_unit();
@@ -1684,11 +1696,17 @@ select_init2:
select_part2
{
LEX *lex= Lex;
+ SELECT_LEX * sel= lex->current_select->select_lex();
if (lex->current_select->set_braces(0))
{
send_error(lex->thd, ER_SYNTAX_ERROR);
YYABORT;
}
+ if (sel->linkage == UNION_TYPE && sel->master_unit()->first_select()->braces)
+ {
+ send_error(lex->thd, ER_SYNTAX_ERROR);
+ YYABORT;
+ }
}
union_clause
;
@@ -1696,6 +1714,7 @@ select_init2:
select_part2:
{
LEX *lex=Lex;
+ SELECT_LEX * sel= lex->current_select->select_lex();
if (lex->current_select == &lex->select_lex)
lex->lock_option= TL_READ; /* Only for global SELECT */
mysql_init_select(lex);
@@ -2018,7 +2037,7 @@ simple_expr:
$$= new Item_row(*$5);
}
| EXISTS exists_subselect { $$= $2; }
- | singleval_subselect { $$= $1; }
+ | singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->add_ftfunc_to_list((Item_func_match *)
@@ -2202,9 +2221,9 @@ simple_expr:
| NOW_SYM '(' expr ')'
{ $$= new Item_func_now($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')'
- {
- $$= new Item_func_password($3);
- }
+ { $$= new Item_func_password($3); }
+ | PASSWORD '(' expr ',' expr ')'
+ { $$= new Item_func_password($3,$5); }
| POINTFROMTEXT '(' expr ')'
{ $$= new Item_func_geometry_from_text($3); }
| POINTFROMTEXT '(' expr ',' expr ')'
@@ -2510,7 +2529,9 @@ join_table:
lex->current_select= unit->outer_select();
if (!($$= lex->current_select->
add_table_to_list(lex->thd, new Table_ident(unit), $5, 0,
- lex->lock_option)))
+ TL_READ,(List<String> *)0,
+ (List<String> *)0)))
+
YYABORT;
};
@@ -3188,16 +3209,16 @@ table_wild_list:
| table_wild_list ',' table_wild_one {};
table_wild_one:
- ident opt_wild
+ ident opt_wild opt_table_alias
{
- if (!Select->add_table_to_list(YYTHD, new Table_ident($1), NULL, 1,
+ if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, 1,
Lex->lock_option))
YYABORT;
}
- | ident '.' ident opt_wild
+ | ident '.' ident opt_wild opt_table_alias
{
if (!Select->add_table_to_list(YYTHD, new Table_ident($1, $3, 0),
- NULL, 1, Lex->lock_option))
+ $5, 1, Lex->lock_option))
YYABORT;
}
;
@@ -4488,17 +4509,17 @@ union_option:
/* empty */ {}
| ALL {Select->master_unit()->union_option= 1;};
-singleval_subselect:
- subselect_start singleval_subselect_init
+singlerow_subselect:
+ subselect_start singlerow_subselect_init
subselect_end
{
$$= $2;
};
-singleval_subselect_init:
+singlerow_subselect_init:
select_init2
{
- $$= new Item_singleval_subselect(YYTHD,
+ $$= new Item_singlerow_subselect(YYTHD,
Lex->current_select->master_unit()->
first_select());
};
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index f5c0a59b572..762c45e7184 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -38,7 +38,7 @@ void safe_print_str(const char* name, const char* val, int max_len)
}
fprintf(stderr, "= ");
- for(; max_len && PTR_SANE(val) && *val; --max_len)
+ for (; max_len && PTR_SANE(val) && *val; --max_len)
fputc(*val++, stderr);
fputc('\n', stderr);
}
@@ -59,7 +59,7 @@ void safe_print_str(const char* name, const char* val, int max_len)
inline uchar** find_prev_fp(uint32* pc, uchar** fp)
{
int i;
- for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
{
uchar* p = (uchar*)pc;
if (p[2] == 222 && p[3] == 35)
@@ -73,7 +73,7 @@ inline uchar** find_prev_fp(uint32* pc, uchar** fp)
inline uint32* find_prev_pc(uint32* pc, uchar** fp)
{
int i;
- for(i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
+ for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc)
{
char* p = (char*)pc;
if (p[1] == 0 && p[2] == 94 && p[3] == -73)
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 573c3c67db0..74ff300c9e9 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -6219,6 +6219,7 @@ CHARSET_INFO my_charset_big5 =
{
1, /* number */
MY_CS_COMPILED, /* state */
+ "big5", /* cs name */
"big5", /* name */
"", /* comment */
ctype_big5,
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 7848862a0db..377e50f3dab 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -260,6 +260,7 @@ static CHARSET_INFO my_charset_bin_st =
{
63, /* number */
MY_CS_COMPILED|MY_CS_BINSORT,/* state */
+ "binary", /* cs name */
"binary", /* name */
"", /* comment */
ctype_bin, /* ctype */
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index d309ddc80c8..bb0afe98032 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -597,6 +597,7 @@ CHARSET_INFO my_charset_czech =
{
2, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"czech", /* name */
"", /* comment */
ctype_czech,
diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c
index 2fe8db85369..6388d4b062f 100644
--- a/strings/ctype-euc_kr.c
+++ b/strings/ctype-euc_kr.c
@@ -8637,6 +8637,7 @@ CHARSET_INFO my_charset_euc_kr =
{
19, /* number */
MY_CS_COMPILED, /* state */
+ "euc_kr", /* cs name */
"euc_kr", /* name */
"", /* comment */
ctype_euc_kr,
diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c
index c06b70011df..77a55f6dadc 100644
--- a/strings/ctype-gb2312.c
+++ b/strings/ctype-gb2312.c
@@ -5687,6 +5687,7 @@ CHARSET_INFO my_charset_gb2312 =
{
24, /* number */
MY_CS_COMPILED, /* state */
+ "gb2312", /* cs name */
"gb2312", /* name */
"", /* comment */
ctype_gb2312,
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 82a75188c24..004c3c778e0 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -9874,6 +9874,7 @@ CHARSET_INFO my_charset_gbk =
{
28, /* number */
MY_CS_COMPILED, /* state */
+ "gbk", /* cs name */
"gbk", /* name */
"", /* comment */
ctype_gbk,
diff --git a/strings/ctype-latin1_de.c b/strings/ctype-latin1_de.c
index 49acd3fa8a8..166e059ef42 100644
--- a/strings/ctype-latin1_de.c
+++ b/strings/ctype-latin1_de.c
@@ -415,6 +415,7 @@ CHARSET_INFO my_charset_latin1_de =
{
31, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"latin1_de", /* name */
"", /* comment */
ctype_latin1_de,
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 092b7aa4f0f..5b963e74db9 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -201,7 +201,7 @@ int my_wildcmp_mb(CHARSET_INFO *cs,
{ // Found w_many
uchar cmp;
const char* mb = wildstr;
- int mblen;
+ int mblen=0;
wildstr++;
/* Remove any '%' and '_' from the wild search string */
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 43db7ebc24a..1e9a5895683 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4461,6 +4461,7 @@ CHARSET_INFO my_charset_sjis =
{
13, /* number */
MY_CS_COMPILED, /* state */
+ "sjis", /* cs name */
"sjis", /* name */
"", /* comment */
ctype_sjis,
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 2dae3036426..b448ebdd926 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -689,6 +689,7 @@ CHARSET_INFO my_charset_tis620 =
{
18, /* number */
MY_CS_COMPILED, /* state */
+ "tis620", /* cs name */
"tis620", /* name */
"", /* comment */
ctype_tis620,
diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c
index 9d970005c85..2c3c8dd11c3 100644
--- a/strings/ctype-ujis.c
+++ b/strings/ctype-ujis.c
@@ -8431,6 +8431,7 @@ CHARSET_INFO my_charset_ujis =
{
12, /* number */
MY_CS_COMPILED, /* state */
+ "ujis", /* cs name */
"ujis", /* name */
"", /* comment */
ctype_ujis,
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index c32592dafec..738bcde92b6 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1959,6 +1959,7 @@ CHARSET_INFO my_charset_utf8 =
{
33, /* number */
MY_CS_COMPILED, /* state */
+ "utf8", /* cs name */
"utf8", /* name */
"", /* comment */
ctype_utf8, /* ctype */
@@ -3025,6 +3026,7 @@ CHARSET_INFO my_charset_ucs2 =
{
35, /* number */
MY_CS_COMPILED, /* state */
+ "ucs2", /* cs name */
"ucs2", /* name */
"", /* comment */
ctype_ucs2, /* ctype */
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index b7a6b21cf4a..0bc63ab07cc 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -623,6 +623,7 @@ CHARSET_INFO my_charset_win1250ch =
{
34, /* number */
MY_CS_COMPILED, /* state */
+ "cp1250", /* cs name */
"win1250ch", /* name */
"", /* comment */
ctype_win1250ch,
diff --git a/strings/ctype.c b/strings/ctype.c
index 8e7d8ad939c..5869ee804c6 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -2811,6 +2811,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
8, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"latin1", /* name */
"", /* comment */
ctype_latin1,
@@ -2856,6 +2857,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
14, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"cp1251", /* name */
"", /* comment */
ctype_cp1251,
@@ -2900,6 +2902,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
29, /* number */
MY_CS_COMPILED, /* state */
+ "cp1257", /* cs name */
"cp1257", /* name */
"", /* comment */
ctype_cp1257,
@@ -2944,6 +2947,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
27, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"croat", /* name */
"", /* comment */
ctype_croat,
@@ -2989,6 +2993,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
15, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"danish", /* name */
"", /* comment */
ctype_danish,
@@ -3033,6 +3038,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
3, /* number */
MY_CS_COMPILED, /* state */
+ "dec8", /* cs name */
"dec8", /* name */
"", /* comment */
ctype_dec8,
@@ -3077,6 +3083,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
4, /* number */
MY_CS_COMPILED, /* state */
+ "cp850", /* cs name */
"dos", /* name */
"", /* comment */
ctype_dos,
@@ -3121,6 +3128,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
20, /* number */
MY_CS_COMPILED, /* state */
+ "latin7", /* cs name */
"estonia", /* name */
"", /* comment */
ctype_estonia,
@@ -3166,6 +3174,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
5, /* number */
MY_CS_COMPILED, /* state */
+ "latin1", /* cs name */
"german1", /* name */
"", /* comment */
ctype_german1,
@@ -3210,6 +3219,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
25, /* number */
MY_CS_COMPILED, /* state */
+ "greek", /* cs name */
"greek", /* name */
"", /* comment */
ctype_greek,
@@ -3254,6 +3264,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
16, /* number */
MY_CS_COMPILED, /* state */
+ "hebrew", /* cs name */
"hebrew", /* name */
"", /* comment */
ctype_hebrew,
@@ -3298,6 +3309,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
6, /* number */
MY_CS_COMPILED, /* state */
+ "hp8", /* cs name */
"hp8", /* name */
"", /* comment */
ctype_hp8,
@@ -3342,6 +3354,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
21, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"hungarian", /* name */
"", /* comment */
ctype_hungarian,
@@ -3386,6 +3399,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
7, /* number */
MY_CS_COMPILED, /* state */
+ "koi8_ru", /* cs name */
"koi8_ru", /* name */
"", /* comment */
ctype_koi8_ru,
@@ -3430,6 +3444,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
22, /* number */
MY_CS_COMPILED, /* state */
+ "koi8_ukr", /* cs name */
"koi8_ukr", /* name */
"", /* comment */
ctype_koi8_ukr,
@@ -3475,6 +3490,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
9, /* number */
MY_CS_COMPILED, /* state */
+ "latin2", /* cs name */
"latin2", /* name */
"", /* comment */
ctype_latin2,
@@ -3519,6 +3535,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
30, /* number */
MY_CS_COMPILED, /* state */
+ "latin5", /* cs name */
"latin5", /* name */
"", /* comment */
ctype_latin5,
@@ -3564,6 +3581,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
10, /* number */
MY_CS_COMPILED, /* state */
+ "swe7", /* cs name */
"swe7", /* name */
"", /* comment */
ctype_swe7,
@@ -3609,6 +3627,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
11, /* number */
MY_CS_COMPILED, /* state */
+ "ascii", /* cs name */
"usa7", /* name */
"", /* comment */
ctype_usa7,
@@ -3653,6 +3672,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
26, /* number */
MY_CS_COMPILED, /* state */
+ "cp1250", /* cs name */
"win1250", /* name */
"", /* comment */
ctype_win1250,
@@ -3697,6 +3717,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
23, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"win1251ukr", /* name */
"", /* comment */
ctype_win1251ukr,
@@ -3741,6 +3762,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
32, /* number */
MY_CS_COMPILED, /* state */
+ "armscii8", /* cs name */
"armscii8", /* name */
"", /* comment */
ctype_armscii8,
@@ -3785,6 +3807,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
17, /* number */
MY_CS_COMPILED, /* state */
+ "cp1251", /* cs name */
"win1251", /* name */
"", /* comment */
ctype_win1251,
@@ -3828,6 +3851,7 @@ static CHARSET_INFO compiled_charsets[] = {
{
0, /* end-of-list marker */
0, /* state */
+ NullS, /* cs name */
NullS, /* name */
NullS, /* comment */
NULL,
diff --git a/tests/client_test.c b/tests/client_test.c
index 280df2bf717..d5e13dd3b43 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -32,14 +32,13 @@
#include <stdio.h>
#include <string.h>
-#include <assert.h>
-
-
/* mysql client headers */
#include <my_sys.h>
#include <mysql.h>
#include <my_getopt.h>
+#include <assert.h>
+
#ifndef true
#define true 1
#endif
@@ -58,100 +57,119 @@ static char *opt_user=0;
static char *opt_password=0;
static char *opt_host=0;
static char *opt_unix_socket=0;
-static uint opt_port;
+static unsigned int opt_port;
static my_bool tty_password=0;
static MYSQL *mysql=0;
-static char query[255];
+static char query[255];
+static char current_db[]= "client_test_db";
-#define myheader(str) { printf("\n\n#######################\n"); \
- printf("%s",str); \
- printf("\n#######################\n"); \
+#define myheader(str) { fprintf(stdout,"\n\n#######################\n"); \
+ fprintf(stdout,"%s",str); \
+ fprintf(stdout,"\n#######################\n"); \
}
#define init_bind(x) (bzero(x,sizeof(x)))
-void print_error(const char *msg)
+#ifndef mysql_param_result
+#define mysql_param_result mysql_prepare_result
+#endif
+
+static void print_error(const char *msg)
{
if (mysql)
{
- fprintf(stderr,"\n [MySQL]%s \n",mysql_error(mysql));
+ if (mysql->server_version)
+ fprintf(stderr,"\n [MySQL-%s]",mysql->server_version);
+ else
+ fprintf(stderr,"\n [MySQL]");
+ fprintf(stderr," %s\n",mysql_error(mysql));
}
- else if(msg) fprintf(stderr, "%s\n", msg);
+ else if(msg) fprintf(stderr, " [MySQL] %s\n", msg);
}
-void print_st_error(MYSQL_STMT *stmt, const char *msg)
+static void print_st_error(MYSQL_STMT *stmt, const char *msg)
{
if (stmt)
{
- fprintf(stderr,"\n [MySQL]%s \n",mysql_stmt_error(stmt));
+ if (stmt->mysql && stmt->mysql->server_version)
+ fprintf(stderr,"\n [MySQL-%s]",stmt->mysql->server_version);
+ else
+ fprintf(stderr,"\n [MySQL]");
+
+ fprintf(stderr," %s\n",mysql_stmt_error(stmt));
}
- else if(msg) fprintf(stderr, "%s\n", msg);
+ else if(msg) fprintf(stderr, " [MySQL] %s\n", msg);
}
+static void client_disconnect();
#define myerror(msg) print_error(msg)
#define mysterror(stmt, msg) print_st_error(stmt, msg)
-#define myassert(x) if(x) {\
- fprintf(stderr,"ASSERTION FAILED AT %d@%s\n",__LINE__, __FILE__);\
- exit(1);\
+#define myassert(exp) \
+ if(!exp) {\
+ client_disconnect(); \
+ fprintf(stderr,"\n"); \
+ assert(exp); \
}
-#define myassert_r(x) if(!x) {\
- fprintf(stderr,"ASSERTION FAILED AT %d@%s\n",__LINE__, __FILE__);\
- exit(1);\
+#define myassert_r(exp) \
+ if(exp) {\
+ client_disconnect(); \
+ fprintf(stderr,"\n"); \
+ assert(!(exp)); \
}
#define myquery(r) \
-if( r != 0) \
{ \
+if( r || r == -1) \
myerror(NULL); \
- myassert(true);\
+ myassert(r == 0); \
}
#define myquery_r(r) \
-if( r != 0) \
{ \
+if( r || r == -1) \
myerror(NULL); \
- myassert_r(true);\
+myassert_r(r == 0); \
}
#define mystmt(stmt,r) \
-if( r != 0) \
{ \
+if( r || r == -1) \
mysterror(stmt,NULL); \
- myassert(true);\
+myassert(r == 0);\
}
-#define myxquery(stmt) \
-if( stmt == 0) \
+#define mystmt_r(stmt,r) \
{ \
- myerror(NULL); \
- myassert(true);\
+if( r || r == -1) \
+ mysterror(stmt,NULL); \
+myassert_r(r == 0);\
}
-#define myxquery_r(stmt) \
-if( stmt == 0) \
+#define mystmt_init(stmt) \
{ \
+if( stmt == 0) \
myerror(NULL); \
- myassert_r(true);\
-} \
-else myassert(true);
+myassert(stmt != 0); \
+}
-#define mystmt_r(stmt,r) \
-if( r != 0) \
+#define mystmt_init_r(stmt) \
{ \
- mysterror(stmt,NULL); \
- myassert_r(true);\
-}
+myassert(stmt == 0);\
+}
#define mytest(x) if(!x) {myerror(NULL);myassert(true);}
#define mytest_r(x) if(x) {myerror(NULL);myassert(true);}
+#define PREPARE(A,B) mysql_prepare(A,B,strlen(B))
+
/********************************************************
* connect to the server *
*********************************************************/
static void client_connect()
{
+ char buff[255];
myheader("client_connect");
if(!(mysql = mysql_init(NULL)))
@@ -163,28 +181,37 @@ static void client_connect()
opt_password, opt_db ? opt_db:"test", opt_port,
opt_unix_socket, 0)))
{
- myerror("connection failed");
+ myerror("connection failed");
+ mysql_close(mysql);
exit(0);
}
/* set AUTOCOMMIT to ON*/
mysql_autocommit(mysql, true);
+ sprintf(buff,"CREATE DATABASE IF NOT EXISTS %s", current_db);
+ mysql_query(mysql, buff);
+ sprintf(buff,"USE %s", current_db);
+ mysql_query(mysql, buff);
}
/********************************************************
* close the connection *
*********************************************************/
-void client_disconnect()
+static void client_disconnect()
{
- myheader("client_disconnect");
-
- mysql_close(mysql);
+ if (mysql)
+ {
+ char buff[255];
+ sprintf(buff,"DROP DATABASE IF EXISTS %s", current_db);
+ mysql_query(mysql, buff);
+ mysql_close(mysql);
+ }
}
/********************************************************
* query processing *
*********************************************************/
-void client_query()
+static void client_query()
{
int rc;
@@ -222,7 +249,7 @@ void client_query()
/********************************************************
* print dashes *
*********************************************************/
-void my_print_dashes(MYSQL_RES *result)
+static void my_print_dashes(MYSQL_RES *result)
{
MYSQL_FIELD *field;
unsigned int i,j;
@@ -244,7 +271,7 @@ void my_print_dashes(MYSQL_RES *result)
/********************************************************
* print resultset metadata information *
*********************************************************/
-void my_print_result_metadata(MYSQL_RES *result)
+static void my_print_result_metadata(MYSQL_RES *result)
{
MYSQL_FIELD *field;
unsigned int i,j;
@@ -287,6 +314,9 @@ int my_process_result_set(MYSQL_RES *result)
MYSQL_FIELD *field;
unsigned int i;
unsigned int row_count=0;
+
+ if (!result)
+ return 0;
my_print_result_metadata(result);
@@ -313,50 +343,157 @@ int my_process_result_set(MYSQL_RES *result)
my_print_dashes(result);
if (mysql_errno(mysql) != 0)
- fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
+ fprintf(stderr, "\n mysql_fetch_row() failed\n");
else
- fprintf(stdout,"\n\t%d rows returned\n", row_count);
+ fprintf(stdout,"\n %d rows returned", row_count);
return(row_count);
}
-static void verify_col_data(const char *table, const char *col, const char *exp_data)
+/********************************************************
+* process the stmt result set *
+*********************************************************/
+uint my_process_stmt_result(MYSQL_STMT *stmt)
{
- MYSQL_STMT *stmt;
- MYSQL_BIND bind[1];
- char data[255];
- int rc;
-
- init_bind(bind);
+ int field_count;
+ uint row_count= 0;
+ MYSQL_BIND buffer[50];
+ MYSQL_FIELD *field;
+ MYSQL_RES *result;
+ char data[50][255];
+ long length[50];
+ int rc, i;
+
+ if (!(result= mysql_prepare_result(stmt)))
+ {
+ while (!mysql_fetch(stmt));
+ return 0;
+ }
- bind[0].buffer_type=FIELD_TYPE_STRING;
- bind[0].buffer= (char *)data;
- bind[0].buffer_length= sizeof(data);
+ field_count= stmt->field_count;
+ for(i=0; i < field_count; i++)
+ {
+ buffer[i].buffer_type= MYSQL_TYPE_STRING;
+ buffer[i].buffer_length=50;
+ buffer[i].length=(long *)&length[i];
+ buffer[i].buffer=(gptr)data[i];
+ }
- sprintf(query, "SELECT `%s` FROM `%s`", col, table);
+ my_print_result_metadata(result);
- printf("\n %s", query);
- stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ rc= mysql_bind_result(stmt,buffer);
+ mystmt(stmt,rc);
- rc = mysql_bind_result(stmt,bind);
- mystmt(stmt, rc);
+ mysql_field_seek(result, 0);
+ while (mysql_fetch(stmt) == 0)
+ {
+ fputc('\t',stdout);
+ fputc('|',stdout);
- rc = mysql_execute(stmt);
- mystmt(stmt, rc);
+ for (i=0; i < field_count; i++)
+ {
+ field = mysql_fetch_field(result);
+ if(length[i] == MYSQL_NULL_DATA)
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
+ }
+ fputc('\t',stdout);
+ fputc('\n',stdout);
+ row_count++;
+ }
+ my_print_dashes(result);
+ fprintf(stdout,"\n %d rows returned", row_count);
+ mysql_free_result(result);
- rc = mysql_fetch(stmt);
- mystmt(stmt,rc);
+ return row_count;
+}
- printf("\n data : %s (expected: %s)",data, exp_data);
- assert(strcmp(data,exp_data)==0);
+/*
+ Utility function to verify a particular column data
+*/
+static void verify_col_data(const char *table, const char *col,
+ const char *exp_data)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ char query[255];
+ int rc, field= 1;
+
+ if (table && col)
+ {
+ sprintf(query, "SELECT %s FROM %s LIMIT 1", col, table);
- mysql_stmt_close(stmt);
+ fprintf(stdout,"\n %s", query);
+ rc = mysql_query(mysql, query);
+ myquery(rc);
+
+ field= 0;
+ }
+
+ result = mysql_use_result(mysql);
+ mytest(result);
+
+ if (!(row= mysql_fetch_row(result)) || !row[field])
+ {
+ fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ fprintf(stdout,"\n obtained: `%s` (expected: `%s`)",
+ row[field], exp_data);
+ myassert(strcmp(row[field],exp_data) == 0);
+ mysql_free_result(result);
+}
+
+/*
+ Utility function to verify the field members
+*/
+
+static void verify_prepare_field(MYSQL_RES *result,
+ unsigned int no,const char *name, const char *org_name,
+ enum enum_field_types type, const char *table,
+ const char *org_table, const char *db)
+{
+ MYSQL_FIELD *field;
+
+ if (!(field= mysql_fetch_field_direct(result,no)))
+ {
+ fprintf(stdout,"\n *** ERROR: FAILED TO GET THE RESULT ***");
+ exit(1);
+ }
+ fprintf(stdout,"\n field[%d]:", no);
+ fprintf(stdout,"\n name :`%s`\t(expected: `%s`)", field->name, name);
+ fprintf(stdout,"\n org_name :`%s`\t(expected: `%s`)", field->org_name, org_name);
+ fprintf(stdout,"\n type :`%d`\t(expected: `%d`)", field->type, type);
+ fprintf(stdout,"\n table :`%s`\t(expected: `%s`)", field->table, table);
+ fprintf(stdout,"\n org_table:`%s`\t(expected: `%s`)", field->org_table, org_table);
+ fprintf(stdout,"\n database :`%s`\t(expected: `%s`)", field->db, db);
+ fprintf(stdout,"\n");
+ myassert(strcmp(field->name,name) == 0);
+ myassert(strcmp(field->org_name,org_name) == 0);
+ myassert(field->type == type);
+ myassert(strcmp(field->table,table) == 0);
+ myassert(strcmp(field->org_table,org_table) == 0);
+ myassert(strcmp(field->db,db) == 0);
+}
+
+/*
+ Utility function to verify the parameter count
+*/
+static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
+{
+ long param_count= mysql_param_count(stmt);
+ fprintf(stdout,"\n total parameters in stmt: %ld (expected: %ld)",
+ param_count, exp_count);
+ myassert(param_count == exp_count);
}
+
/********************************************************
* store result processing *
*********************************************************/
-void client_store_result()
+static void client_store_result()
{
MYSQL_RES *result;
int rc;
@@ -375,9 +512,9 @@ void client_store_result()
}
/********************************************************
-* use result processing *
+* fetch the results
*********************************************************/
-void client_use_result()
+static void client_use_result()
{
MYSQL_RES *result;
int rc;
@@ -398,7 +535,7 @@ void client_use_result()
/********************************************************
* query processing *
*********************************************************/
-void test_debug_example()
+static void test_debug_example()
{
int rc;
MYSQL_RES *result;
@@ -418,7 +555,7 @@ void test_debug_example()
rc = mysql_query(mysql,"UPDATE test_debug_example SET name='updated' WHERE name='deleted'");
myquery(rc);
- rc = mysql_query(mysql,"SELECT * FROM test_debug_example");
+ rc = mysql_query(mysql,"SELECT * FROM test_debug_example where name='mysql'");
myquery(rc);
result = mysql_use_result(mysql);
@@ -434,7 +571,7 @@ void test_debug_example()
/********************************************************
* to test autocommit feature *
*********************************************************/
-void test_tran_bdb()
+static void test_tran_bdb()
{
MYSQL_RES *result;
MYSQL_ROW row;
@@ -512,7 +649,7 @@ void test_tran_bdb()
/********************************************************
* to test autocommit feature *
*********************************************************/
-void test_tran_innodb()
+static void test_tran_innodb()
{
MYSQL_RES *result;
MYSQL_ROW row;
@@ -591,10 +728,10 @@ void test_tran_innodb()
To test simple prepares of all DML statements
*********************************************************/
-void test_prepare_simple()
+static void test_prepare_simple()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
myheader("test_prepare_simple");
@@ -610,41 +747,33 @@ void test_prepare_simple()
/* alter table */
strcpy(query,"ALTER TABLE test_prepare_simple ADD new char(20)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in alter:%d\n", param_count);
- assert(param_count == 0);
+ verify_param_count(stmt,0);
mysql_stmt_close(stmt);
/* insert */
strcpy(query,"INSERT INTO test_prepare_simple VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
mysql_stmt_close(stmt);
/* update */
strcpy(query,"UPDATE test_prepare_simple SET id=? WHERE id=? AND name= ?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in update:%d\n", param_count);
- assert(param_count == 3);
+ verify_param_count(stmt,3);
mysql_stmt_close(stmt);
/* delete */
strcpy(query,"DELETE FROM test_prepare_simple WHERE id=10");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in delete:%d\n", param_count);
- assert(param_count == 0);
+ verify_param_count(stmt,0);
rc = mysql_execute(stmt);
mystmt(stmt, rc);
@@ -653,11 +782,9 @@ void test_prepare_simple()
/* delete */
strcpy(query,"DELETE FROM test_prepare_simple WHERE id=?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in delete:%d\n", param_count);
- assert(param_count == 1);
+ verify_param_count(stmt,1);
rc = mysql_execute(stmt);
mystmt_r(stmt, rc);
@@ -666,11 +793,9 @@ void test_prepare_simple()
/* select */
strcpy(query,"SELECT * FROM test_prepare_simple WHERE id=? AND name= ?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in select:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
mysql_stmt_close(stmt);
@@ -683,9 +808,10 @@ void test_prepare_simple()
/********************************************************
* to test simple prepare field results *
*********************************************************/
-void test_prepare_field_result()
+static void test_prepare_field_result()
{
MYSQL_STMT *stmt;
+ MYSQL_RES *result;
int rc,param_count;
myheader("test_prepare_field_result");
@@ -696,29 +822,47 @@ void test_prepare_field_result()
rc = mysql_commit(mysql);
myquery(rc);
- rc = mysql_query(mysql,"CREATE TABLE test_prepare_field_result(id int, name varchar(50), extra int)");
+ rc = mysql_query(mysql,"CREATE TABLE test_prepare_field_result(int_c int, \
+ var_c varchar(50), ts_c timestamp(14),\
+ char_c char(3), date_c date,extra tinyint)");
myquery(rc);
/* insert */
- strcpy(query,"SELECT id,name FROM test_prepare_field_result WHERE id=?");
+ strcpy(query,"SELECT int_c,var_c,date_c as date,ts_c,char_c FROM \
+ test_prepare_field_result as t1 WHERE int_c=?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout,"\n total parameters in insert:%d\n", param_count);
- assert(param_count == 1);
- mysql_stmt_close(stmt);
+ verify_param_count(stmt,1);
- /* now fetch the results ..*/
- rc = mysql_commit(mysql);
- myquery(rc);
+ result = mysql_prepare_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ fprintf(stdout,"\n\n field attributes:\n");
+ verify_prepare_field(result,0,"int_c","int_c",MYSQL_TYPE_LONG,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,1,"var_c","var_c",MYSQL_TYPE_VAR_STRING,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,2,"date","date_c",MYSQL_TYPE_DATE,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,3,"ts_c","ts_c",MYSQL_TYPE_TIMESTAMP,
+ "t1","test_prepare_field_result",current_db);
+ verify_prepare_field(result,4,"char_c","char_c",MYSQL_TYPE_STRING,
+ "t1","test_prepare_field_result",current_db);
+
+ param_count= mysql_num_fields(result);
+ fprintf(stdout,"\n\n total fields: `%d` (expected: `5`)", param_count);
+ myassert(param_count == 5);
+ mysql_stmt_close(stmt);
}
/********************************************************
* to test simple prepare field results *
*********************************************************/
-void test_prepare_syntax()
+static void test_prepare_syntax()
{
MYSQL_STMT *stmt;
int rc;
@@ -736,11 +880,11 @@ void test_prepare_syntax()
strcpy(query,"INSERT INTO test_prepare_syntax VALUES(?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery_r(stmt);
+ mystmt_init_r(stmt);
strcpy(query,"SELECT id,name FROM test_prepare_syntax WHERE id=? AND WHERE");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery_r(stmt);
+ mystmt_init_r(stmt);
/* now fetch the results ..*/
rc = mysql_commit(mysql);
@@ -751,10 +895,10 @@ void test_prepare_syntax()
/********************************************************
* to test simple prepare *
*********************************************************/
-void test_prepare()
+static void test_prepare()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char query[200];
int int_data;
char str_data[50];
@@ -779,7 +923,7 @@ void test_prepare()
myquery(rc);
rc = mysql_query(mysql,"CREATE TABLE my_prepare(col1 tinyint,\
- col2 varchar(50), col3 int,\
+ col2 varchar(15), col3 int,\
col4 smallint, col5 bigint, \
col6 float, col7 double )");
myquery(rc);
@@ -787,11 +931,9 @@ void test_prepare()
/* insert by prepare */
strcpy(query,"INSERT INTO my_prepare VALUES(?,?,?,?,?,?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 7);
+ verify_param_count(stmt,7);
/* tinyint */
bind[0].buffer_type=FIELD_TYPE_TINY;
@@ -852,7 +994,7 @@ void test_prepare()
result = mysql_store_result(mysql);
mytest(result);
- assert((int)tiny_data == my_process_result_set(result));
+ myassert((int)tiny_data == my_process_result_set(result));
mysql_free_result(result);
}
@@ -860,10 +1002,10 @@ void test_prepare()
/********************************************************
* to test double comparision *
*********************************************************/
-void test_double_compare()
+static void test_double_compare()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char query[200],real_data[10], tiny_data;
double double_data;
MYSQL_RES *result;
@@ -890,10 +1032,9 @@ void test_double_compare()
strcpy(query, "UPDATE test_double_compare SET col1=100 WHERE col1 = ? AND col2 = ? AND COL3 = ?");
stmt = mysql_prepare(mysql,query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in update:%d\n", param_count);
+ verify_param_count(stmt,3);
/* tinyint */
bind[0].buffer_type=FIELD_TYPE_TINY;
@@ -916,7 +1057,7 @@ void test_double_compare()
mystmt(stmt, rc);
rc = (int)mysql_affected_rows(mysql);
- printf("\n total affected rows:%d",rc);
+ fprintf(stdout,"\n total affected rows:%d",rc);
mysql_stmt_close(stmt);
@@ -932,21 +1073,17 @@ void test_double_compare()
result = mysql_store_result(mysql);
mytest(result);
- assert((int)tiny_data == my_process_result_set(result));
+ myassert((int)tiny_data == my_process_result_set(result));
mysql_free_result(result);
-
}
-
-
-
/********************************************************
* to test simple null *
*********************************************************/
-void test_null()
+static void test_null()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
int nData=1;
MYSQL_RES *result;
MYSQL_BIND bind[2];
@@ -966,15 +1103,13 @@ void test_null()
/* insert by prepare, wrong column name */
strcpy(query,"INSERT INTO test_null(col3,col2) VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery_r(stmt);
+ mystmt_init_r(stmt);
strcpy(query,"INSERT INTO test_null(col1,col2) VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
bind[0].is_null=1;
bind[0].buffer_type=MYSQL_TYPE_NULL;
@@ -1003,49 +1138,171 @@ void test_null()
result = mysql_store_result(mysql);
mytest(result);
- assert(nData == my_process_result_set(result));
+ myassert(nData == my_process_result_set(result));
mysql_free_result(result);
}
+/********************************************************
+* to test fetch null *
+*********************************************************/
+static void test_fetch_null()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char query[100];
+ int length[11], i, nData;
+ MYSQL_BIND bind[11];
+
+ myheader("test_fetch_null");
+
+ init_bind(bind);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_fetch_null");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_fetch_null(col1 tinyint, col2 smallint, \
+ col3 int, col4 bigint, \
+ col5 float, col6 double, \
+ col7 date, col8 time, \
+ col9 varbinary(10), \
+ col10 varchar(50),\
+ col11 char(20))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_fetch_null(col11) VALUES(1000)");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* fetch */
+ for (i=0; i < 10; i++)
+ {
+ bind[i].buffer_type=FIELD_TYPE_LONG;
+ length[i]=99;
+ bind[i].length= (long *)&length[i];
+ }
+ bind[i].buffer_type=FIELD_TYPE_LONG;
+ bind[i].buffer=(gptr)&nData;
+
+ strcpy((char *)query , "SELECT * FROM test_fetch_null");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ for (i=0; i < 10; i++)
+ {
+ fprintf(stdout, "\n data[%d]: %s", i, length[i] == MYSQL_NULL_DATA ? "NULL" : "NOT NULL");
+ myassert(length[i] == MYSQL_NULL_DATA);
+ }
+ fprintf(stdout, "\n data[%d]: %d", i, nData);
+ myassert(nData == 1000);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
/********************************************************
* to test simple select *
*********************************************************/
-void test_select_simple()
+static void test_select_version()
{
MYSQL_STMT *stmt;
- int rc,length;
+ int rc;
+ const char query[100];
+
+ myheader("test_select_version");
+
+ strcpy((char *)query , "SELECT @@version");
+ stmt = PREPARE(mysql, query);
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test simple select *
+*********************************************************/
+static void test_select_simple()
+{
+ MYSQL_STMT *stmt;
+ int rc;
const char query[100];
- MYSQL_RES *result;
myheader("test_select_simple");
/* insert by prepare */
strcpy((char *)query, "SHOW TABLES FROM mysql");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- length = mysql_param_count(stmt);
- fprintf(stdout," total parameters in select:%d\n", length);
- assert(length == 0);
+ verify_param_count(stmt,0);
rc = mysql_execute(stmt);
mystmt(stmt, rc);
- /* get the result */
- result = mysql_store_result(mysql);
- mytest(result);
+ my_process_stmt_result(stmt);
+ mysql_stmt_close(stmt);
+}
- my_process_result_set(result);
- mysql_free_result(result);
+/********************************************************
+* to test simple select to debug *
+*********************************************************/
+static void test_select_direct()
+{
+ int rc;
+ MYSQL_RES *result;
- mysql_stmt_close(stmt);
+ myheader("test_select_direct");
+
+ rc = mysql_autocommit(mysql,true);
+ myquery(rc);
-#if 0
- strcpy((char *)query , "SELECT @@ VERSION");
- length = strlen(query);
- rc = mysql_query(mysql,query);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id int, id1 tinyint, \
+ id2 float, \
+ id3 double, \
+ name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,5,2.3,4.5,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"SELECT * FROM test_select");
myquery(rc);
/* get the result */
@@ -1054,22 +1311,88 @@ void test_select_simple()
my_process_result_set(result);
mysql_free_result(result);
-#endif
}
+/********************************************************
+* to test simple select with prepare *
+*********************************************************/
+static void test_select_prepare()
+{
+ int rc, count;
+ MYSQL_STMT *stmt;
+
+ myheader("test_select_prepare");
+
+ rc = mysql_autocommit(mysql,true);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id int, name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select VALUES(10,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_select",50);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ count= my_process_stmt_result(stmt);
+
+ rc = mysql_query(mysql,"DROP TABLE test_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_select(id tinyint, id1 int, \
+ id2 float, id3 float, \
+ name varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ /* insert a row and commit the transaction */
+ rc = mysql_query(mysql,"INSERT INTO test_select(id,id1,id2,name) VALUES(10,5,2.3,'venu')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ stmt = mysql_prepare(mysql,"SELECT * FROM test_select",25);
+ mystmt_init(stmt);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ my_process_stmt_result(stmt);
+}
/********************************************************
* to test simple select *
*********************************************************/
-void test_select()
+static void test_select()
{
MYSQL_STMT *stmt;
- int rc,param_count=0;
- char *szData=(char *)"updated-value";
+ int rc;
+ char szData[25];
int nData=1;
MYSQL_BIND bind[2];
- MYSQL_RES *result;
-
myheader("test_select");
@@ -1105,15 +1428,13 @@ void test_select()
strcpy(query,"SELECT * FROM test_select WHERE id=? AND name=?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in select:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
/* string data */
nData=10;
- szData=(char *)"venu";
+ strcpy(szData,(char *)"venu");
bind[1].buffer_type=FIELD_TYPE_STRING;
bind[1].buffer=szData;
bind[1].buffer_length=4;
@@ -1126,28 +1447,50 @@ void test_select()
rc = mysql_execute(stmt);
mystmt(stmt, rc);
+ myassert( 1 == my_process_stmt_result(stmt));
+
+ mysql_stmt_close(stmt);
+}
+
+/********************************************************
+* to test simple select show *
+*********************************************************/
+static void test_select_show()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ MYSQL_RES *result;
+
+ myheader("test_select_show");
+
+ mysql_autocommit(mysql,true);
+
+ strcpy(query,"SELECT * FROM mysql.host");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
/* get the result */
result = mysql_store_result(mysql);
mytest(result);
- assert( 1 == my_process_result_set(result));
+ my_process_result_set(result);
mysql_free_result(result);
mysql_stmt_close(stmt);
-
- /* bit complicated SELECT */
}
-
-
-
/********************************************************
* to test simple update *
*********************************************************/
-void test_simple_update()
+static void test_simple_update()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char szData[25];
int nData=1;
MYSQL_RES *result;
@@ -1175,7 +1518,7 @@ void test_simple_update()
rc = mysql_query(mysql,"INSERT INTO test_update VALUES(1,'MySQL',100)");
myquery(rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
rc = mysql_commit(mysql);
myquery(rc);
@@ -1183,11 +1526,9 @@ void test_simple_update()
/* insert by prepare */
strcpy(query,"UPDATE test_update SET col2=? WHERE col1=?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in update:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
nData=1;
bind[0].buffer_type=FIELD_TYPE_STRING;
@@ -1201,7 +1542,7 @@ void test_simple_update()
rc = mysql_execute(stmt);
mystmt(stmt, rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
mysql_stmt_close(stmt);
@@ -1217,7 +1558,7 @@ void test_simple_update()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
}
@@ -1225,10 +1566,10 @@ void test_simple_update()
/********************************************************
* to test simple long data handling *
*********************************************************/
-void test_long_data()
+static void test_long_data()
{
MYSQL_STMT *stmt;
- int rc,param_count, int_data=10;
+ int rc, int_data;
char *data=NullS;
MYSQL_RES *result;
MYSQL_BIND bind[3];
@@ -1255,15 +1596,13 @@ void test_long_data()
strcpy(query,"INSERT INTO test_long_data(col1,col2) VALUES(?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery_r(stmt);
+ mystmt_init_r(stmt);
strcpy(query,"INSERT INTO test_long_data(col1,col2,col3) VALUES(?,?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 3);
+ verify_param_count(stmt,3);
bind[0].buffer=(char *)&int_data;
bind[0].buffer_type=FIELD_TYPE_LONG;
@@ -1272,7 +1611,7 @@ void test_long_data()
/* Non string or binary type, error */
bind[1].buffer_type=FIELD_TYPE_LONG;
rc = mysql_bind_param(stmt,bind);
- fprintf(stdout,"mysql_bind_param() returned %d\n",rc);
+ fprintf(stdout," mysql_bind_param() returned: %d\n",rc);
mystmt_r(stmt, rc);
bind[1].buffer_type=FIELD_TYPE_STRING;
@@ -1280,36 +1619,37 @@ void test_long_data()
rc = mysql_bind_param(stmt,bind);
mystmt(stmt, rc);
+ int_data= 999;
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
data = (char *)"Micheal";
/* supply data in pieces */
- rc = mysql_send_long_data(stmt,1,data,7,1);
+ rc = mysql_send_long_data(stmt,1,data,7,0);
mystmt(stmt, rc);
/* try to execute mysql_execute() now, it should return
MYSQL_NEED_DATA as the long data supply is not yet over
*/
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
/* append data again ..*/
/* Indicate end of data */
- data = (char *)" 'monty' widenius";
+ data = (char *)" 'monty' Widenius";
rc = mysql_send_long_data(stmt,1,data,17,1);
mystmt(stmt, rc);
- rc = mysql_send_long_data(stmt,2,"Venu (venu@mysql.com",4,1);
+ rc = mysql_send_long_data(stmt,2,"Venu (venu@mysql.com)",4,1);
mystmt(stmt, rc);
/* execute */
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
mystmt(stmt,rc);
rc = mysql_commit(mysql);
@@ -1323,17 +1663,21 @@ void test_long_data()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
+
+ verify_col_data("test_long_data","col1","999");
+ verify_col_data("test_long_data","col2","Micheal 'monty' Widenius");
+ verify_col_data("test_long_data","col3","Venu");
}
/********************************************************
* to test long data (string) handling *
*********************************************************/
-void test_long_data_str()
+static void test_long_data_str()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc, i;
char data[255];
long length;
MYSQL_RES *result;
@@ -1360,11 +1704,9 @@ void test_long_data_str()
strcpy(query,"INSERT INTO test_long_data_str VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
bind[0].buffer = (gptr)&length;
bind[0].buffer_type = FIELD_TYPE_LONG;
@@ -1377,28 +1719,24 @@ void test_long_data_str()
length = 10;
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
length = 40;
sprintf(data,"MySQL AB");
/* supply data in pieces */
+ for(i=0; i < 4; i++)
{
- int i;
- for(i=0; i < 4; i++)
- {
- rc = mysql_send_long_data(stmt,1,(char *)data,5,0);
- mystmt(stmt, rc);
- }
-
- /* try to execute mysql_execute() now, it should return
- MYSQL_NEED_DATA as the long data supply is not yet over
- */
- rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ rc = mysql_send_long_data(stmt,1,(char *)data,5,0);
+ mystmt(stmt, rc);
}
+ /* try to execute mysql_execute() now, it should return
+ MYSQL_NEED_DATA as the long data supply is not yet over
+ */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
/* Indiate end of data supply */
rc = mysql_send_long_data(stmt,1,0,0,1);
@@ -1406,7 +1744,7 @@ void test_long_data_str()
/* execute */
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
mystmt(stmt,rc);
mysql_stmt_close(stmt);
@@ -1422,20 +1760,27 @@ void test_long_data_str()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
+
+ sprintf(data,"%d", i*5);
+ verify_col_data("test_long_data_str","LENGTH(longstr)", data);
+ data[0]='\0';
+ while (i--)
+ sprintf(data,"%s%s", data,"MySQL");
+ verify_col_data("test_long_data_str","longstr", data);
}
/********************************************************
* to test long data (string) handling *
*********************************************************/
-void test_long_data_str1()
+static void test_long_data_str1()
{
MYSQL_STMT *stmt;
- int rc,param_count;
- char *data=(char *)"MySQL AB";
- int length;
+ int rc;
+ char data[255];
+ int length, i;
MYSQL_RES *result;
MYSQL_BIND bind[2];
@@ -1460,11 +1805,9 @@ void test_long_data_str1()
strcpy(query,"INSERT INTO test_long_data_str VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
bind[0].buffer=data; /* string data */
bind[0].is_long_data=1; /* specify long data suppy during run-time */
@@ -1478,44 +1821,41 @@ void test_long_data_str1()
length = 10;
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
- length = strlen(data);
+ length = sprintf(data,"MySQL AB");
/* supply data in pieces */
+ for(i=0; i < 3; i++)
{
- int i;
- for(i=0; i < 2; i++)
- {
- rc = mysql_send_long_data(stmt,0,data,length,0);
- mystmt(stmt, rc);
+ rc = mysql_send_long_data(stmt,0,data,length,0);
+ mystmt(stmt, rc);
- rc = mysql_send_long_data(stmt,1,data,2,0);
- mystmt(stmt, rc);
- }
- /* try to execute mysql_execute() now, it should return
- MYSQL_NEED_DATA as the long data supply is not yet over
- */
- rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ rc = mysql_send_long_data(stmt,1,data,2,0);
+ mystmt(stmt, rc);
}
-
+ /* try to execute mysql_execute() now, it should return
+ MYSQL_NEED_DATA as the long data supply is not yet over
+ */
+ rc = mysql_execute(stmt);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
+
/* Indiate end of data supply */
rc = mysql_send_long_data(stmt,1,0,0,1);
mystmt(stmt, rc);
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
rc = mysql_send_long_data(stmt,0,0,0,1);
mystmt(stmt, rc);
/* execute */
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
mystmt(stmt,rc);
mysql_stmt_close(stmt);
@@ -1531,18 +1871,24 @@ void test_long_data_str1()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
+
+ sprintf(data,"%d",i*length);
+ verify_col_data("test_long_data_str","length(longstr)",data);
+
+ sprintf(data,"%d",i*2);
+ verify_col_data("test_long_data_str","length(blb)",data);
}
/********************************************************
* to test long data (binary) handling *
*********************************************************/
-void test_long_data_bin()
+static void test_long_data_bin()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char data[255];
int length;
MYSQL_RES *result;
@@ -1569,11 +1915,9 @@ void test_long_data_bin()
strcpy(query,"INSERT INTO test_long_data_bin VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
bind[0].buffer = (gptr)&length;
bind[0].buffer_type = FIELD_TYPE_LONG;
@@ -1586,8 +1930,8 @@ void test_long_data_bin()
length = 10;
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
sprintf(data,"MySQL AB");
@@ -1604,8 +1948,8 @@ void test_long_data_bin()
MYSQL_NEED_DATA as the long data supply is not yet over
*/
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
- assert(rc == MYSQL_NEED_DATA);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
+ myassert(rc == MYSQL_NEED_DATA);
}
/* Indiate end of data supply */
@@ -1614,7 +1958,7 @@ void test_long_data_bin()
/* execute */
rc = mysql_execute(stmt);
- fprintf(stdout,"mysql_execute() returned %d\n",rc);
+ fprintf(stdout," mysql_execute() returned %d\n",rc);
mystmt(stmt,rc);
mysql_stmt_close(stmt);
@@ -1630,7 +1974,7 @@ void test_long_data_bin()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
}
@@ -1638,10 +1982,10 @@ void test_long_data_bin()
/********************************************************
* to test simple delete *
*********************************************************/
-void test_simple_delete()
+static void test_simple_delete()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char szData[30]={0};
int nData=1;
MYSQL_RES *result;
@@ -1670,7 +2014,7 @@ void test_simple_delete()
rc = mysql_query(mysql,"INSERT INTO test_simple_delete VALUES(1,'MySQL',100)");
myquery(rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
rc = mysql_commit(mysql);
myquery(rc);
@@ -1678,11 +2022,9 @@ void test_simple_delete()
/* insert by prepare */
strcpy(query,"DELETE FROM test_simple_delete WHERE col1=? AND col2=? AND col3=100");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in delete:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
nData=1;
strcpy(szData,"MySQL");
@@ -1697,7 +2039,7 @@ void test_simple_delete()
rc = mysql_execute(stmt);
mystmt(stmt, rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
mysql_stmt_close(stmt);
@@ -1713,7 +2055,7 @@ void test_simple_delete()
result = mysql_store_result(mysql);
mytest(result);
- assert(0 == my_process_result_set(result));
+ myassert(0 == my_process_result_set(result));
mysql_free_result(result);
}
@@ -1722,10 +2064,10 @@ void test_simple_delete()
/********************************************************
* to test simple update *
*********************************************************/
-void test_update()
+static void test_update()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char szData[25];
int nData=1;
MYSQL_RES *result;
@@ -1753,11 +2095,9 @@ void test_update()
strcpy(query,"INSERT INTO test_update(col2,col3) VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
/* string data */
bind[0].buffer_type=FIELD_TYPE_STRING;
@@ -1773,16 +2113,14 @@ void test_update()
rc = mysql_execute(stmt);
mystmt(stmt, rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
mysql_stmt_close(stmt);
strcpy(query,"UPDATE test_update SET col2=? WHERE col3=?");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in update:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
nData=100;
@@ -1797,7 +2135,7 @@ void test_update()
rc = mysql_execute(stmt);
mystmt(stmt, rc);
- assert(1 == mysql_affected_rows(mysql));
+ myassert(1 == mysql_affected_rows(mysql));
mysql_stmt_close(stmt);
@@ -1813,7 +2151,7 @@ void test_update()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
}
@@ -1821,13 +2159,13 @@ void test_update()
/********************************************************
* to test simple prepare *
*********************************************************/
-void test_init_prepare()
+static void test_prepare_noparam()
{
MYSQL_STMT *stmt;
- int param_count, rc;
+ int rc;
MYSQL_RES *result;
- myheader("test_init_prepare");
+ myheader("test_prepare_noparam");
rc = mysql_query(mysql,"DROP TABLE IF EXISTS my_prepare");
myquery(rc);
@@ -1842,11 +2180,9 @@ void test_init_prepare()
/* insert by prepare */
strcpy(query,"INSERT INTO my_prepare VALUES(10,'venu')");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 0);
+ verify_param_count(stmt,0);
rc = mysql_execute(stmt);
mystmt(stmt, rc);
@@ -1865,7 +2201,7 @@ void test_init_prepare()
result = mysql_store_result(mysql);
mytest(result);
- assert(1 == my_process_result_set(result));
+ myassert(1 == my_process_result_set(result));
mysql_free_result(result);
}
@@ -1873,12 +2209,12 @@ void test_init_prepare()
/********************************************************
* to test simple bind result *
*********************************************************/
-void test_bind_result()
+static void test_bind_result()
{
MYSQL_STMT *stmt;
int rc;
const char query[100];
- int nData;
+ int nData, length, length1;
char szData[100];
MYSQL_BIND bind[2];
@@ -1903,6 +2239,9 @@ void test_bind_result()
rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(20,'MySQL')");
myquery(rc);
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result(col2) VALUES('monty')");
+ myquery(rc);
+
rc = mysql_commit(mysql);
myquery(rc);
@@ -1910,13 +2249,131 @@ void test_bind_result()
bind[0].buffer_type=FIELD_TYPE_LONG;
bind[0].buffer= (gptr) &nData; /* integer data */
+ bind[0].length= (long *)&length;
bind[1].buffer_type=FIELD_TYPE_STRING;
bind[1].buffer=szData; /* string data */
bind[1].buffer_length=sizeof(szData);
+ bind[1].length=(long *)&length1;
+
+ strcpy((char *)query , "SELECT * FROM test_bind_result");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 1: %d,%s(%d)",nData, szData, length1);
+ myassert(nData == 10);
+ myassert(strcmp(szData,"venu")==0);
+ myassert(length1 == 4);
+
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout,"\n row 2: %d,%s(%d)",nData, szData, length1);
+ myassert(nData == 20);
+ myassert(strcmp(szData,"MySQL")==0);
+ myassert(length1 == 5);
+
+ length=99;
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ if (length == MYSQL_NULL_DATA)
+ fprintf(stdout,"\n row 3: NULL,%s(%d)", szData, length1);
+ else
+ fprintf(stdout,"\n row 3: %d,%s(%d)", nData, szData, length1);
+ myassert(length == MYSQL_NULL_DATA);
+ myassert(strcmp(szData,"monty")==0);
+ myassert(length1 == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test ext bind result *
+*********************************************************/
+static void test_bind_result_ext()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char query[100];
+ uchar t_data;
+ short s_data;
+ int i_data;
+ longlong b_data;
+ float f_data;
+ double d_data;
+ char szData[20], bData[20];
+ int szLength, bLength;
+ MYSQL_BIND bind[8];
+
+ myheader("test_bind_result_ext");
+
+ init_bind(bind);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ c3 int, c4 bigint, \
+ c5 float, c6 double, \
+ c7 varbinary(10), \
+ c8 varchar(50))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(19,2999,3999,4999999,\
+ 2345.6,5678.89563,\
+ 'venu','mysql')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind[0].buffer_type=MYSQL_TYPE_TINY;
+ bind[0].buffer=(gptr)&t_data;
+
+ bind[1].buffer_type=MYSQL_TYPE_SHORT;
+ bind[2].buffer_type=MYSQL_TYPE_LONG;
+
+ bind[3].buffer_type=MYSQL_TYPE_LONGLONG;
+ bind[1].buffer=(gptr)&s_data;
+
+ bind[2].buffer=(gptr)&i_data;
+ bind[3].buffer=(gptr)&b_data;
+
+ bind[4].buffer_type=MYSQL_TYPE_FLOAT;
+ bind[4].buffer=(gptr)&f_data;
+
+ bind[5].buffer_type=MYSQL_TYPE_DOUBLE;
+ bind[5].buffer=(gptr)&d_data;
+
+ bind[6].buffer_type=MYSQL_TYPE_STRING;
+ bind[6].buffer=(gptr)&szData;
+ bind[6].length=(long *)&szLength;
+
+ bind[7].buffer_type=MYSQL_TYPE_TINY_BLOB;
+ bind[7].buffer=(gptr)&bData;
+ bind[7].length=(long *)&bLength;
strcpy((char *)query , "SELECT * FROM test_bind_result");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
rc = mysql_bind_result(stmt,bind);
mystmt(stmt, rc);
@@ -1927,30 +2384,281 @@ void test_bind_result()
rc = mysql_fetch(stmt);
mystmt(stmt,rc);
- printf("\n row 1:%d,%s",nData, szData);
- assert(nData == 10);
- assert(strcmp(szData,"venu")==0);
+ fprintf(stdout, "\n data (tiny) : %d", t_data);
+ fprintf(stdout, "\n data (short) : %d", s_data);
+ fprintf(stdout, "\n data (int) : %d", i_data);
+ fprintf(stdout, "\n data (big) : %lld", b_data);
+
+ fprintf(stdout, "\n data (float) : %f", f_data);
+ fprintf(stdout, "\n data (double) : %f", d_data);
+
+ fprintf(stdout, "\n data (str) : %s(%d)", szData, szLength);
+ fprintf(stdout, "\n data (bin) : %s(%d)", bData, bLength);
+
+
+ myassert(t_data == 19);
+ myassert(s_data == 2999);
+ myassert(i_data == 3999);
+ myassert(b_data == 4999999);
+ /*myassert(f_data == 2345.60);*/
+ /*myassert(d_data == 5678.89563);*/
+ myassert(strcmp(szData,"venu")==0);
+ myassert(strcmp(bData,"mysql")==0);
+ myassert(szLength == 4);
+ myassert(bLength == 5);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
+* to test ext bind result *
+*********************************************************/
+static void test_bind_result_ext1()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ const char query[100];
+ char t_data[20];
+ float s_data;
+ short i_data;
+ short b_data;
+ int f_data;
+ long bData;
+ long length[11];
+ char d_data[20];
+ double szData;
+ MYSQL_BIND bind[8];
+
+ myheader("test_bind_result_ext1");
+
+ init_bind(bind);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
+ c3 int, c4 bigint, \
+ c5 float, c6 double, \
+ c7 varbinary(10), \
+ c8 varchar(10))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES(120,2999,3999,54,\
+ 2.6,58.89,\
+ '206','6.7')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind[0].buffer_type=MYSQL_TYPE_STRING;
+ bind[0].buffer=(gptr)t_data;
+
+ for (rc=0; rc <= 7; rc++)
+ bind[rc].length= &length[rc];
+
+ bind[1].buffer_type=MYSQL_TYPE_FLOAT;
+ bind[1].buffer=(gptr)&s_data;
+
+ bind[2].buffer_type=MYSQL_TYPE_SHORT;
+ bind[2].buffer=(gptr)&i_data;
+
+ bind[3].buffer_type=MYSQL_TYPE_TINY;
+ bind[3].buffer=(gptr)&b_data;
+
+ bind[4].buffer_type=MYSQL_TYPE_LONG;
+ bind[4].buffer=(gptr)&f_data;
+
+ bind[5].buffer_type=MYSQL_TYPE_STRING;
+ bind[5].buffer=(gptr)d_data;
+
+ bind[6].buffer_type=MYSQL_TYPE_LONG;
+ bind[6].buffer=(gptr)&bData;
+
+ bind[7].buffer_type=MYSQL_TYPE_DOUBLE;
+ bind[7].buffer=(gptr)&szData;
+
+ strcpy((char *)query , "SELECT * FROM test_bind_result");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
rc = mysql_fetch(stmt);
mystmt(stmt,rc);
- printf("\n row 2:%d,%s",nData, szData);
- assert(nData == 20);
- assert(strcmp(szData,"MySQL")==0);
+ fprintf(stdout, "\n data (tiny) : %s(%ld)", t_data, length[0]);
+ fprintf(stdout, "\n data (short) : %f(%ld)", s_data, length[1]);
+ fprintf(stdout, "\n data (int) : %d(%ld)", i_data, length[2]);
+ fprintf(stdout, "\n data (big) : %d(%ld)", b_data, length[3]);
+
+ fprintf(stdout, "\n data (float) : %d(%ld)", f_data, length[4]);
+ fprintf(stdout, "\n data (double) : %s(%ld)", d_data, length[5]);
+
+ fprintf(stdout, "\n data (bin) : %ld(%ld)", bData, length[6]);
+ fprintf(stdout, "\n data (str) : %g(%ld)", szData, length[7]);
+
+ myassert(strcmp(t_data,"120")==0);
+ myassert(i_data == 3999);
+ myassert(f_data == 2);
+ myassert(strcmp(d_data,"58.89")==0);
+
+ myassert(length[0] == 3);
+ myassert(length[1] == 4);
+ myassert(length[2] == 2);
+ myassert(length[3] == 1);
+ myassert(length[4] == 4);
+ myassert(length[5] == 5);
+ myassert(length[6] == 4);
+ myassert(length[7] == 8);
rc = mysql_fetch(stmt);
- assert(rc == MYSQL_NO_DATA);
+ myassert(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
}
/********************************************************
+* to test fetching of date, time and ts *
+*********************************************************/
+static void test_fetch_date()
+{
+ MYSQL_STMT *stmt;
+ int rc, year;
+ char date[25], time[25], ts[25], ts_4[15], ts_6[20], dt[20];
+ int d_length, t_length, ts_length, ts4_length, ts6_length,
+ dt_length, y_length;
+
+ MYSQL_BIND bind[3];
+
+ myheader("test_fetch_date");
+
+ init_bind(bind);
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_bind_result");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_bind_result(c1 date, c2 time, \
+ c3 timestamp(14), \
+ c4 year, \
+ c5 datetime, \
+ c6 timestamp(4), \
+ c7 timestamp(6))");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"INSERT INTO test_bind_result VALUES('2002-01-02',\
+ '12:49:00',\
+ '2002-01-02 17:46:59', \
+ 2010,\
+ '2010-07-10', \
+ '2020','1999-12-29')");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ bind[0].buffer_type=MYSQL_TYPE_STRING;
+ bind[1]=bind[2]=bind[0];
+
+ bind[0].buffer=(gptr)&date;
+ bind[0].length=(long *)&d_length;
+
+ bind[1].buffer=(gptr)&time;
+ bind[1].length=(long *)&t_length;
+
+ bind[2].buffer=(gptr)&ts;
+ bind[2].length=(long *)&ts_length;
+
+ bind[3].buffer_type=MYSQL_TYPE_LONG;
+ bind[3].buffer=(gptr)&year;
+ bind[3].length=(long *)&y_length;
+
+ bind[4].buffer_type=MYSQL_TYPE_STRING;
+ bind[4].buffer=(gptr)&dt;
+ bind[4].length=(long *)&dt_length;
+
+ bind[5].buffer_type=MYSQL_TYPE_STRING;
+ bind[5].buffer=(gptr)&ts_4;
+ bind[5].length=(long *)&ts4_length;
+
+ bind[6].buffer_type=MYSQL_TYPE_STRING;
+ bind[6].buffer=(gptr)&ts_6;
+ bind[6].length=(long *)&ts6_length;
+
+ stmt = mysql_prepare(mysql, "SELECT * FROM test_bind_result", 50);
+ mystmt_init(stmt);
+
+ rc = mysql_bind_result(stmt,bind);
+ mystmt(stmt, rc);
+
+ rc = mysql_execute(stmt);
+ mystmt(stmt, rc);
+
+ ts_4[0]='\0';
+ rc = mysql_fetch(stmt);
+ mystmt(stmt,rc);
+
+ fprintf(stdout, "\n date : %s(%d)", date, d_length);
+ fprintf(stdout, "\n time : %s(%d)", time, t_length);
+ fprintf(stdout, "\n ts : %s(%d)", ts, ts_length);
+ fprintf(stdout, "\n year : %d(%d)", year, y_length);
+ fprintf(stdout, "\n dt : %s(%d)", dt, dt_length);
+ fprintf(stdout, "\n ts(4) : %s(%d)", ts_4, ts4_length);
+ fprintf(stdout, "\n ts(6) : %s(%d)", ts_6, ts6_length);
+
+ myassert(strcmp(date,"2002-01-02")==0);
+ myassert(d_length == 10);
+
+ myassert(strcmp(time,"12:49:00")==0);
+ myassert(d_length == 8);
+
+ myassert(strcmp(ts,"2002-01-02 17:46:59")==0);
+ myassert(ts_length == 19);
+
+ myassert(year == 2010);
+ myassert(y_length == 4);
+
+ myassert(strcmp(dt,"2010-07-10")==0);
+ myassert(dt_length == 10);
+
+ myassert(ts_4[0] == '\0');
+ myassert(ts4_length == 0);
+
+ myassert(strcmp(ts_6,"1999-12-29")==0);
+ myassert(ts6_length == 10);
+
+ rc = mysql_fetch(stmt);
+ myassert(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+}
+
+
+/********************************************************
* to test simple prepare with all possible types *
*********************************************************/
-void test_prepare_ext()
+static void test_prepare_ext()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char *sql;
int nData=1;
MYSQL_RES *result;
@@ -2012,9 +2720,7 @@ void test_prepare_ext()
stmt = mysql_prepare(mysql,query, strlen(query));
myquery(rc);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 6);
+ verify_param_count(stmt,6);
/*tinyint*/
bind_int[0].buffer_type=FIELD_TYPE_TINY;
@@ -2065,7 +2771,7 @@ void test_prepare_ext()
result = mysql_store_result(mysql);
mytest(result);
- assert(nData == my_process_result_set(result));
+ myassert(nData == my_process_result_set(result));
mysql_free_result(result);
}
@@ -2075,14 +2781,14 @@ void test_prepare_ext()
/********************************************************
* to test real and alias names *
*********************************************************/
-void test_field_names()
+static void test_field_names()
{
int rc;
MYSQL_RES *result;
myheader("test_field_names");
- printf("\n%d,%d,%d",MYSQL_TYPE_DECIMAL,MYSQL_TYPE_NEWDATE,MYSQL_TYPE_ENUM);
+ fprintf(stdout,"\n %d,%d,%d",MYSQL_TYPE_DECIMAL,MYSQL_TYPE_NEWDATE,MYSQL_TYPE_ENUM);
rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_field_names1");
myquery(rc);
@@ -2108,7 +2814,7 @@ void test_field_names()
result = mysql_use_result(mysql);
mytest(result);
- assert(0 == my_process_result_set(result));
+ myassert(0 == my_process_result_set(result));
mysql_free_result(result);
/* with table name included with true column name */
@@ -2118,23 +2824,20 @@ void test_field_names()
result = mysql_use_result(mysql);
mytest(result);
- assert(0 == my_process_result_set(result));
+ myassert(0 == my_process_result_set(result));
mysql_free_result(result);
}
/********************************************************
* to test warnings *
*********************************************************/
-void test_warnings()
+static void test_warnings()
{
int rc;
MYSQL_RES *result;
myheader("test_warnings");
- rc = mysql_query(mysql,"USE test");
- myquery(rc);
-
rc = mysql_query(mysql,"SHOW WARNINGS");
myquery(rc);
@@ -2148,7 +2851,7 @@ void test_warnings()
/********************************************************
* to test errors *
*********************************************************/
-void test_errors()
+static void test_errors()
{
int rc;
MYSQL_RES *result;
@@ -2170,10 +2873,10 @@ void test_errors()
/********************************************************
* to test simple prepare-insert *
*********************************************************/
-void test_insert()
+static void test_insert()
{
MYSQL_STMT *stmt;
- int rc,param_count, length;
+ int rc, length;
char query[200];
char str_data[50];
char tiny_data;
@@ -2199,11 +2902,9 @@ void test_insert()
bzero(bind, sizeof(bind));
strcpy(query,"INSERT INTO test_prep_insert VALUES(?,?)");
stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,2);
/* tinyint */
bind[0].buffer_type=FIELD_TYPE_TINY;
@@ -2238,7 +2939,7 @@ void test_insert()
result = mysql_store_result(mysql);
mytest(result);
- assert((int)tiny_data == my_process_result_set(result));
+ myassert((int)tiny_data == my_process_result_set(result));
mysql_free_result(result);
}
@@ -2246,10 +2947,10 @@ void test_insert()
/********************************************************
* to test simple prepare-resultset info *
*********************************************************/
-void test_prepare_resultset()
+static void test_prepare_resultset()
{
MYSQL_STMT *stmt;
- int rc,param_count;
+ int rc;
char query[200];
MYSQL_RES *result;
@@ -2268,38 +2969,15 @@ void test_prepare_resultset()
name varchar(50),extra double)");
myquery(rc);
- /* insert by prepare */
- strcpy(query,"INSERT INTO test_prepare_resultset(id,name) VALUES(?,?)");
- stmt = mysql_prepare(mysql, query, strlen(query));
- myxquery(stmt);
+ strcpy(query,"SELECT * FROM test_prepare_resultset");
+ stmt = PREPARE(mysql, query);
+ mystmt_init(stmt);
- param_count = mysql_param_count(stmt);
- fprintf(stdout," total parameters in insert:%d\n", param_count);
- assert(param_count == 2);
+ verify_param_count(stmt,0);
- rc = mysql_query(mysql,"SELECT * FROM test_prepare_resultset");
- myquery(rc);
-
- /* get the prepared-result */
result = mysql_prepare_result(stmt);
- assert( result != 0);
-
- my_print_result_metadata(result);
- mysql_free_result(result);
-
- result = mysql_store_result(mysql);
mytest(result);
-
- assert(0 == my_process_result_set(result));
- mysql_free_result(result);
-
- /* get the prepared-result */
- result = mysql_prepare_result(stmt);
- assert( result != 0);
-
my_print_result_metadata(result);
- mysql_free_result(result);
-
mysql_stmt_close(stmt);
}
@@ -2307,7 +2985,7 @@ void test_prepare_resultset()
* to test field flags (verify .NET provider) *
*********************************************************/
-void test_field_flags()
+static void test_field_flags()
{
int rc;
MYSQL_RES *result;
@@ -2348,22 +3026,459 @@ void test_field_flags()
for(i=0; i< mysql_num_fields(result); i++)
{
field = mysql_fetch_field(result);
- printf("\nfield:%d",i);
+ fprintf(stdout,"\n field:%d",i);
if(field->flags & NOT_NULL_FLAG)
- printf("\n NOT_NULL_FLAG");
+ fprintf(stdout,"\n NOT_NULL_FLAG");
if(field->flags & PRI_KEY_FLAG)
- printf("\n PRI_KEY_FLAG");
+ fprintf(stdout,"\n PRI_KEY_FLAG");
if(field->flags & UNIQUE_KEY_FLAG)
- printf("\n UNIQUE_KEY_FLAG");
+ fprintf(stdout,"\n UNIQUE_KEY_FLAG");
if(field->flags & MULTIPLE_KEY_FLAG)
- printf("\n MULTIPLE_KEY_FLAG");
+ fprintf(stdout,"\n MULTIPLE_KEY_FLAG");
if(field->flags & AUTO_INCREMENT_FLAG)
- printf("\n AUTO_INCREMENT_FLAG");
+ fprintf(stdout,"\n AUTO_INCREMENT_FLAG");
}
mysql_free_result(result);
}
+/**************************************************************
+ * Test mysql_stmt_close for open stmts *
+**************************************************************/
+static void test_stmt_close()
+{
+ MYSQL *lmysql;
+ MYSQL_STMT *stmt1, *stmt2, *stmt3, *stmt_x;
+ MYSQL_BIND param[1];
+ MYSQL_RES *result;
+ char query[100];
+ unsigned int count;
+ int rc;
+
+ myheader("test_stmt_close");
+
+ init_bind(param);
+ if(!(lmysql = mysql_init(NULL)))
+ {
+ myerror("mysql_init() failed");
+ exit(0);
+ }
+ if (!(mysql_real_connect(lmysql,opt_host,opt_user,
+ opt_password, opt_db ? opt_db:"inter_client_test_db", opt_port,
+ opt_unix_socket, 0)))
+ {
+ myerror("connection failed");
+ exit(0);
+ }
+ if (opt_db)
+ strcpy(current_db,opt_db);
+
+ /* set AUTOCOMMIT to ON*/
+ mysql_autocommit(lmysql, true);
+ mysql_query(lmysql,"DROP TABLE IF EXISTS test_stmt_close");
+ mysql_query(lmysql,"CREATE TABLE test_stmt_close(id int)");
+
+ strcpy(query,"ALTER TABLE test_stmt_close ADD name varchar(20)");
+ stmt1= PREPARE(lmysql, query);
+ mystmt_init(stmt1);
+ count= mysql_param_count(stmt1);
+ fprintf(stdout,"\n total params in alter: %d", count);
+ myassert(count == 0);
+ strcpy(query,"INSERT INTO test_stmt_close(id) VALUES(?)");
+ stmt_x= PREPARE(mysql, query);
+ mystmt_init(stmt_x);
+ count= mysql_param_count(stmt_x);
+ fprintf(stdout,"\n total params in insert: %d", count);
+ myassert(count == 1);
+ strcpy(query,"UPDATE test_stmt_close SET id=? WHERE id=?");
+ stmt3= PREPARE(lmysql, query);
+ mystmt_init(stmt3);
+ count= mysql_param_count(stmt3);
+ fprintf(stdout,"\n total params in update: %d", count);
+ myassert(count == 2);
+ strcpy(query,"SELECT * FROM test_stmt_close WHERE id=?");
+ stmt2= PREPARE(lmysql, query);
+ mystmt_init(stmt2);
+ count= mysql_param_count(stmt2);
+ fprintf(stdout,"\n total params in select: %d", count);
+ myassert(count == 1);
+
+ rc= mysql_stmt_close(stmt1);
+ fprintf(stdout,"\n mysql_close_stmt(1) returned: %d", rc);
+ myassert(rc == 0);
+ mysql_close(lmysql); /* it should free all stmts */
+#if NOT_VALID
+ rc= mysql_stmt_close(stmt3);
+ fprintf(stdout,"\n mysql_close_stmt(3) returned: %d", rc);
+ myassert( rc == 1);
+ rc= mysql_stmt_close(stmt2);
+ fprintf(stdout,"\n mysql_close_stmt(2) returned: %d", rc);
+ myassert( rc == 1);
+#endif
+
+ count= 100;
+ param[0].buffer=(gptr)&count;
+ param[0].buffer_type=MYSQL_TYPE_LONG;
+ rc = mysql_bind_param(stmt_x, param);
+ mystmt(stmt_x, rc);
+ rc = mysql_execute(stmt_x);
+ mystmt(stmt_x, rc);
+
+ rc= (ulong)mysql_affected_rows(stmt_x->mysql);
+ fprintf(stdout,"\n total rows affected: %d", rc);
+ myassert (rc == 1);
+
+ rc= mysql_stmt_close(stmt_x);
+ fprintf(stdout,"\n mysql_close_stmt(x) returned: %d", rc);
+ myassert( rc == 0);
+
+ /*verify_col_data("test_stmt_close", "id", "100");*/
+ rc = mysql_query(mysql,"SELECT id FROM test_stmt_close");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ myassert(1 == my_process_result_set(result));
+ mysql_free_result(result);
+}
+
+/********************************************************
+ * To test simple set-variable prepare *
+*********************************************************/
+static void test_set_variable()
+{
+ MYSQL_STMT *stmt;
+ int rc, select_limit=88;
+ char query[200];
+ MYSQL_BIND bind[1];
+ MYSQL_RES *result;
+
+
+ myheader("test_set_variable");
+
+ rc = mysql_autocommit(mysql, true);
+ myquery(rc);
+
+ strcpy(query,"SET GLOBAL delayed_insert_limit=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,1);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ init_bind(bind);
+
+ bind[0].buffer_type= MYSQL_TYPE_LONG;
+ bind[0].buffer=(gptr)&select_limit;
+
+ rc = mysql_bind_param(stmt, bind);
+ mystmt(stmt,rc);
+
+ rc= mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ mysql_store_result(mysql);
+
+ strcpy(query,"show variables like 'delayed_insert_limit'");
+ rc = mysql_query(mysql,query);
+ myquery(rc);
+
+ verify_col_data(NullS, NullS, "88");
+
+#if TO_BE_FIXED
+
+ select_limit= 100;/* reset to default */
+ rc= mysql_execute(stmt);
+ mystmt(stmt,rc);
+
+ mysql_store_result(mysql);
+ mysql_stmt_close(stmt);
+
+ rc = mysql_query(mysql,query);
+ myquery(rc);
+
+ verify_col_data(NullS, NullS, "100");
+#endif
+ mysql_stmt_close(stmt);
+}
+#if NOT_USED
+/* Insert meta info .. */
+static void test_insert_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[200];
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_insert_meta");
+
+ rc = mysql_autocommit(mysql, true);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_insert");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_insert(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strcpy(query,"INSERT INTO test_prep_insert VALUES(10,'venu1','test')");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ strcpy(query,"INSERT INTO test_prep_insert VALUES(?,'venu',?)");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1");
+ myassert(strcmp(field->name,"col1")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3");
+ myassert(strcmp(field->name,"col3")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+
+/* Update meta info .. */
+static void test_update_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[200];
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_update_meta");
+
+ rc = mysql_autocommit(mysql, true);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_update");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_update(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strcpy(query,"UPDATE test_prep_update SET col1=10, col2='venu1' WHERE col3='test'");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ strcpy(query,"UPDATE test_prep_update SET col1=?, col2='venu' WHERE col3=?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ myassert(strcmp(field->name,"col1")==0);
+ myassert(strcmp(field->table,"test_prep_update")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ myassert(strcmp(field->name,"col3")==0);
+ myassert(strcmp(field->table,"test_prep_update")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+
+/* Select meta info .. */
+static void test_select_meta()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[200];
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_select_meta");
+
+ rc = mysql_autocommit(mysql, true);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_prep_select");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_prep_select(col1 tinyint,\
+ col2 varchar(50), col3 varchar(30))");
+ myquery(rc);
+
+ strcpy(query,"SELECT * FROM test_prep_select WHERE col1=10");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,0);
+
+ result= mysql_param_result(stmt);
+ mytest_r(result);
+
+ strcpy(query,"SELECT col1, col3 from test_prep_select WHERE col1=? AND col3='test' AND col2= ?");
+ stmt = mysql_prepare(mysql, query, strlen(query));
+ mystmt_init(stmt);
+
+ verify_param_count(stmt,2);
+
+ result= mysql_param_result(stmt);
+ mytest(result);
+
+ my_print_result_metadata(result);
+
+ mysql_field_seek(result, 0);
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ myassert(strcmp(field->name,"col1")==0);
+ myassert(strcmp(field->table,"test_prep_select")==0);
+
+ field= mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ myassert(strcmp(field->name,"col2")==0);
+ myassert(strcmp(field->table,"test_prep_select")==0);
+
+ field= mysql_fetch_field(result);
+ mytest_r(field);
+
+ mysql_free_result(result);
+ mysql_stmt_close(stmt);
+}
+#endif
+
+/* Test FUNCTION field info / DATE_FORMAT() table_name . */
+static void test_func_fields()
+{
+ int rc;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+
+ myheader("test_func_fields");
+
+ rc = mysql_autocommit(mysql, true);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"DROP TABLE IF EXISTS test_dateformat");
+ myquery(rc);
+
+ rc = mysql_commit(mysql);
+ myquery(rc);
+
+ rc = mysql_query(mysql,"CREATE TABLE test_dateformat(id int, \
+ ts timestamp)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
+ myquery(rc);
+
+ rc = mysql_query(mysql, "SELECT ts FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table,
+ "test_dateformat");
+ myassert(strcmp(field->table, "test_dateformat")==0);
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+
+ /* DATE_FORMAT */
+ rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'venu' FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n table name: `%s` (expected: `%s`)", field->table, "");
+ myassert(field->table[0] == '\0');
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+
+ /* FIELD ALIAS TEST */
+ rc = mysql_query(mysql, "SELECT DATE_FORMAT(ts,'%Y') AS 'YEAR' FROM test_dateformat");
+ myquery(rc);
+
+ result = mysql_store_result(mysql);
+ mytest(result);
+
+ field = mysql_fetch_field(result);
+ mytest(field);
+ fprintf(stdout,"\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
+ fprintf(stdout,"\n field org name: `%s` (expected: `%s`)",field->org_name,"");
+ myassert(strcmp(field->name, "YEAR")==0);
+ myassert(field->org_name[0] == '\0');
+
+ field = mysql_fetch_field(result);
+ mytest_r(field); /* no more fields */
+
+ mysql_free_result(result);
+}
+
static struct my_option myctest_long_options[] =
{
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
@@ -2398,24 +3513,24 @@ static void usage(void)
puts("and you are welcome to modify and redistribute it under the GPL license\n");
puts(" Copyright (C) 1995-2002 MySQL AB ");
puts("-----------------------------------------------------------------------\n");
- printf("usage: %s [OPTIONS]\n\n", my_progname);
- printf("\
+ fprintf(stdout,"usage: %s [OPTIONS]\n\n", my_progname);
+ fprintf(stdout,"\
-?, --help Display this help message and exit.\n\
-D --database=... Database name to be used for test.\n\
-h, --host=... Connect to host.\n\
-p, --password[=...] Password to use when connecting to server.\n");
#ifdef __WIN__
- printf("\
+ fprintf(stdout,"\
-W, --pipe Use named pipes to connect to server.\n");
#endif
- printf("\
+ fprintf(stdout,"\
-P, --port=... Port number to use for connection.\n\
-S, --socket=... Socket file to use for connection.\n");
#ifndef DONT_ALLOW_USER_CHANGE
- printf("\
+ fprintf(stdout,"\
-u, --user=# User for login if not current user.\n");
#endif
- printf("*********************************************************************\n");
+ fprintf(stdout,"*********************************************************************\n");
}
static my_bool
@@ -2471,24 +3586,52 @@ int main(int argc, char **argv)
MY_INIT(argv[0]);
get_options(argc,argv);
- client_connect(); /* connect to server */
-
+ client_connect(); /* connect to server */
+ test_select_prepare();
+ test_prepare();
+ test_prepare_simple();
+ test_bind_result(); /* result bind test */
+ test_fetch_null(); /* to fetch null data */
+ test_fetch_date();
+ test_bind_result_ext(); /* result bind test - extension */
+ test_bind_result_ext1(); /* result bind test - extension */
+ test_select_direct(); /* direct select - protocol_simple debug */
+ test_select_prepare(); /* prepare select - protocol_prep debug */
+ test_select_direct(); /* direct select - protocol_simple debug */
+ test_select();
+ test_select_version();
+ test_set_variable(); /* set variable prepare */
+#if NOT_USED
+ test_select_meta(); /* select param meta information */
+ test_update_meta(); /* update param meta information */
+ test_insert_meta(); /* insert param meta information */
+#endif
+ test_simple_update(); /* simple update test */
+ test_func_fields();
+ test_long_data();
+ test_insert();
+ test_set_variable();
+ test_tran_innodb();
+ test_select_version();
+ test_select_simple();
+ test_debug_example();
+ test_select();
+ test_select_show();
test_null(); /* test null data handling */
- test_simple_update();
- //test_select_simple();
- //test_prepare_resultset();
- //test_select(); /* simple prepare-select */
+ test_simple_update();
+ test_prepare_resultset();
+ test_prepare_noparam();/* prepare without parameters */
+ test_select(); /* simple prepare-select */
test_insert(); /* prepare with insert */
- //test_bind_result(); /* result bind test */
- //test_long_data(); /* long data handling in pieces */
+ test_bind_result(); /* result bind test */
+ test_long_data(); /* long data handling in pieces */
test_prepare_simple();/* simple prepare */
test_prepare(); /* prepare test */
- test_prepare_simple();/* simple prepare */
test_null(); /* test null data handling */
test_debug_example(); /* some debugging case */
test_update(); /* prepare-update test */
test_simple_update(); /* simple prepare with update */
- //test_long_data(); /* long data handling in pieces */
+ test_long_data(); /* long data handling in pieces */
test_simple_delete(); /* prepare with delete */
test_field_names(); /* test for field names */
test_double_compare();/* float comparision */
@@ -2499,20 +3642,23 @@ int main(int argc, char **argv)
test_tran_innodb(); /* transaction test on InnoDB table type */
test_prepare_ext(); /* test prepare with all types conversion -- TODO */
test_prepare_syntax();/* syntax check for prepares */
- //test_prepare_field_result(); /* prepare meta info */
+ test_prepare_field_result(); /* prepare meta info */
+ test_prepare_resultset();
test_field_names(); /* test for field names */
test_field_flags(); /* test to help .NET provider team */
- //test_long_data_str(); /* long data handling */
- //test_long_data_str1();/* yet another long data handling */
- //test_long_data_bin(); /* long binary insertion */
+ test_long_data_str(); /* long data handling */
+ test_long_data_str1();/* yet another long data handling */
+ test_long_data_bin(); /* long binary insertion */
test_warnings(); /* show warnings test */
test_errors(); /* show errors test */
- //test_select_simple(); /* simple select prepare */
- //test_prepare_resultset();/* prepare meta info test */
-
+ test_select_simple(); /* simple select prepare */
+ test_prepare_resultset();/* prepare meta info test */
+ test_func_fields(); /* FUNCTION field info */
+ /*test_stmt_close(); */ /* mysql_stmt_close() test -- hangs */
+ test_prepare_field_result(); /* prepare meta info */
client_disconnect(); /* disconnect from server */
-
- fprintf(stdout,"\ndone !!!\n");
+
+ fprintf(stdout,"\n\nSUCCESS !!!\n");
return(0);
}