Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
cde22b02
Commit
cde22b02
authored
Feb 05, 2003
by
venu@myvenu.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added all new changes (To be incorporated to main manual before the release)
parent
03fd42e6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
440 additions
and
126 deletions
+440
-126
Docs/prepare.texi
Docs/prepare.texi
+440
-126
No files found.
Docs/prepare.texi
View file @
cde22b02
...
@@ -117,6 +117,8 @@
...
@@ -117,6 +117,8 @@
* C Prepared statement datatypes::
* C Prepared statement datatypes::
* C Prepared statements function overview::
* C Prepared statements function overview::
* C Prepared statement functions::
* C Prepared statement functions::
* multiple queries::
* date handling::
@end menu
@end menu
@node C Prepared statements, C Prepared statement datatypes, MySQL prepared statements, MySQL prepared statements
@node C Prepared statements, C Prepared statement datatypes, MySQL prepared statements, MySQL prepared statements
...
@@ -160,8 +162,10 @@ Prepared statements mainly uses the following two @code{MYSQL_STMT} and
...
@@ -160,8 +162,10 @@ Prepared statements mainly uses the following two @code{MYSQL_STMT} and
@sp 1
@sp 1
@table @code
@table @code
@tindex MYSQL C type
@tindex MYSQL
_
STMT C type
@item MYSQL
_
STMT
@item MYSQL
_
STMT
This structure represents a statement handle to prepared statements.It
This structure represents a statement handle to prepared statements.It
is used for all statement related functions.
is used for all statement related functions.
...
@@ -178,11 +182,14 @@ the system resources.
...
@@ -178,11 +182,14 @@ the system resources.
@sp 1
@sp 1
@tindex MYSQL
_
BIND C type
@tindex MYSQL
_
BIND C type
@item MYSQL
_
BIND
@item MYSQL
_
BIND
This structure is used in order to bind parameter buffers inorder to
send the parameters data to @code
{
mysql
_
execute()
}
call; as well as to
This structure is used in order to bind parameter
bind row buffers to fetch the result set data using @code
{
mysql
_
fetch()
}
.
buffers(@code
{
mysql
_
bind
_
param()
}
) inorder to the parameters data to
@end table
@code
{
mysql
_
execute()
}
call; as well as to bind row
buffers(@code
{
mysql
_
bind
_
result()
}
) to fetch the result set data using
@code
{
mysql
_
fetch()
}
.
@sp 1
@sp 1
...
@@ -191,6 +198,7 @@ The @code{MYSQL_BIND} structure contains the members listed here:
...
@@ -191,6 +198,7 @@ The @code{MYSQL_BIND} structure contains the members listed here:
@table @code
@table @code
@item enum enum
_
field
_
types buffer
_
type [input]
@item enum enum
_
field
_
types buffer
_
type [input]
The type of the buffer. The @code
{
type
}
value must be one of the following:
The type of the buffer. The @code
{
type
}
value must be one of the following:
...
@@ -202,6 +210,10 @@ The type of the buffer. The @code{type} value must be one of the following:
...
@@ -202,6 +210,10 @@ The type of the buffer. The @code{type} value must be one of the following:
@item @code
{
MYSQL
_
TYPE
_
LONGLONG
}
@item @code
{
MYSQL
_
TYPE
_
LONGLONG
}
@item @code
{
MYSQL
_
TYPE
_
FLOAT
}
@item @code
{
MYSQL
_
TYPE
_
FLOAT
}
@item @code
{
MYSQL
_
TYPE
_
DOUBLE
}
@item @code
{
MYSQL
_
TYPE
_
DOUBLE
}
@item @code
{
MYSQL
_
TYPE
_
TIME
}
@item @code
{
MYSQL
_
TYPE
_
DATE
}
@item @code
{
MYSQL
_
TYPE
_
DATETIME
}
@item @code
{
MYSQL
_
TYPE
_
TIMESTAMP
}
@item @code
{
MYSQL
_
TYPE
_
STRING
}
@item @code
{
MYSQL
_
TYPE
_
STRING
}
@item @code
{
MYSQL
_
TYPE
_
VAR
_
STRING
}
@item @code
{
MYSQL
_
TYPE
_
VAR
_
STRING
}
@item @code
{
MYSQL
_
TYPE
_
TINY
_
BLOB
}
@item @code
{
MYSQL
_
TYPE
_
TINY
_
BLOB
}
...
@@ -218,49 +230,62 @@ data when the structure is used for result set bind.
...
@@ -218,49 +230,62 @@ data when the structure is used for result set bind.
@sp 1
@sp 1
@item unsigned long buffer
_
length [input]
Length of the @code
{
*buffer
}
in bytes. For character and binary C data,
the buffer
_
length specifies the length of the @code
{
*buffer
}
to be used
as a parameter data in case if it is used with @code
{
mysql
_
bind
_
param()
}
or to return that many bytes when fetching results when this is used
with @code
{
mysql
_
bind
_
result()
}
.
@item long *length [input/output]
@item long *length [input/output]
Pointer to the buffer for the parameter's length. When the structure is
Pointer to the buffer for the parameter's length. When the structure is
used as a input parameter data binding, then this argument points to a
used as a input parameter data binding, then this argument points to a
buffer that, when @code
{
mysql
_
execute()
}
is called, contains one of the
buffer that, when @code
{
mysql
_
execute()
}
is called, contains the length
following:
of the parameter value stored in *buffer. This is ignored except for
character or binary C data.
@itemize @bullet
@item
The length of the parameter value stored in *buffer. This is ignored
except for character or binary C data.
@item
MYSQL
_
NULL
_
DATA. The parameter value is NULL.
@item
MYSQL
_
LONG
_
DATA. The parameter value is a long data and is supplied in
chunks through @code
{
mysql
_
send
_
long
_
data()
}
.
@end itemize
If the length is a null pointer, then the protocol assumes that all
If the length is a null pointer, then the protocol assumes that all
input parameter values are non-NULL and that character and binary data
character and binary data are null terminated.
are null terminated.
When this structure is used in output binding, then @code
{
mysql
_
fetch()
}
When this structure is used in output binding, then @code
{
mysql
_
fetch()
}
return the
following values in the length buffer:
return the
the length of the data that is returned.
@itemize @bullet
@sp 1
@item
The length of the data that is returned
@item bool *is
_
null [input/output]
@item
Indicates if the parameter data is NULL or fetched data is NULL.
MYSQL
_
NULL
_
DATA, indicating the data returned is a NULL data.
@end table
@end itemize
@sp 1
@tindex MySQL C type
@c @item bool is
_
null [input]
@item MYSQL
_
TIME
@c To indicate the parameter data is NULL. This is same as supplying
@c MYSQL
_
NULL
_
DATA, -1 as the length in length pointer.
This structure is used to send and receive DATE, TIME and
TIMESTAMP data directly to/from server.
@c @item bool is
_
long
_
data [input]
@sp 1
@c To indicate the parameter data is a long data, and the data will be
@c supplied in chunks through @code
{
mysql
_
send
_
long
_
data()
}
.This is also
@noindent
@c same as supplying MYSQL
_
LONG
_
DATA, -2 as the length in length pointer.
The @code
{
MYSQL
_
TIME
}
structure contains the members listed here:
@c @end table
@multitable @columnfractions .20 .20 .68
@item @strong
{
Member
}
@tab @strong
{
Type
}
@tab @strong
{
Description
}
@item @code
{
year
}
@tab unsigned int @tab Year.
@item @code
{
month
}
@tab unsigned int @tab Month of the year.
@item @code
{
day
}
@tab unsigned int @tab Day of the month.
@item @code
{
hour
}
@tab unsigned int @tab Hour of the day(TIME).
@item @code
{
minute
}
@tab unsigned int @tab Minute of the hour.
@item @code
{
second
}
@tab unsigned int @tab Second of the minute.
@item @code
{
neg
}
@tab my
_
bool @tab A boolean flag to
indicate if the time is negative.
@item @code
{
second
_
part
}
@tab unsigned long @tab Fraction part of the
second(not yet used)
@end multitable
@end table
@end table
...
@@ -289,7 +314,10 @@ are described in greater detail in the later section.
...
@@ -289,7 +314,10 @@ are described in greater detail in the later section.
@item @strong
{
mysql
_
stmt
_
affected
_
rows()
}
@tab Returns the number of rows changes/deleted/inserted by the last UPDATE,DELETE,or INSERT query
@item @strong
{
mysql
_
stmt
_
affected
_
rows()
}
@tab Returns the number of rows changes/deleted/inserted by the last UPDATE,DELETE,or INSERT query
@item @strong
{
mysql
_
bind
_
result()
}
@tab Binds application data buffers to columns in the resultset.
@item @strong
{
mysql
_
bind
_
result()
}
@tab Binds application data buffers
to columns in the resultset.
@item @strong
{
mysql
_
stmt
_
store
_
result()
}
@tab Retrieves the complete result set to the client
@item @strong
{
mysql
_
fetch()
}
@tab Fetches the next rowset of data from the result set and returns data for all bound columns.
@item @strong
{
mysql
_
fetch()
}
@tab Fetches the next rowset of data from the result set and returns data for all bound columns.
...
@@ -315,6 +343,7 @@ are described in greater detail in the later section.
...
@@ -315,6 +343,7 @@ are described in greater detail in the later section.
@end multitable
@end multitable
@sp 1
@sp 1
Call @code
{
mysql
_
prepare()
}
to prepare and initialize the statement
Call @code
{
mysql
_
prepare()
}
to prepare and initialize the statement
handle, then call @code
{
mysql
_
bind
_
param()
}
to supply the parameters
handle, then call @code
{
mysql
_
bind
_
param()
}
to supply the parameters
data, and then call @code
{
mysql
_
execute()
}
to execute the query. You can
data, and then call @code
{
mysql
_
execute()
}
to execute the query. You can
...
@@ -421,7 +450,7 @@ You can get the statement error code and message using
...
@@ -421,7 +450,7 @@ You can get the statement error code and message using
@code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
respectively.
@code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
respectively.
@node C Prepared statement functions,
, C Prepared statements function overview, MySQL prepared statements
@node C Prepared statement functions,
multiple queries, C Prepared statements function overview, MySQL prepared statements
@subsection C Prepared Statement Function Descriptions
@subsection C Prepared Statement Function Descriptions
You need to use the following functions when you want to prepare and
You need to use the following functions when you want to prepare and
...
@@ -429,21 +458,24 @@ execute the queries.
...
@@ -429,21 +458,24 @@ execute the queries.
@menu
@menu
* mysql
_
prepare::
* mysql
_
prepare:: @code
{
mysql
_
prepare()
}
* mysql
_
param
_
count::
* mysql
_
param
_
count:: @code
{
mysql
_
param
_
count()
}
* mysql
_
prepare
_
result::
* mysql
_
prepare
_
result:: @code
{
mysql
_
prepare
_
result()
}
* mysql
_
bind
_
param::
* mysql
_
bind
_
param:: @code
{
mysql
_
bind
_
param()
}
* mysql
_
execute::
* mysql
_
execute:: @code
{
mysql
_
execute()
}
* mysql
_
stmt
_
affected
_
rows::
* mysql
_
stmt
_
affected
_
rows:: @code
{
mysql
_
stmt
_
affected
_
rows()
}
* mysql
_
bind
_
result::
* mysql
_
bind
_
result:: @code
{
mysql
_
bind
_
result()
}
* mysql
_
fetch::
* mysql
_
stmt
_
store
_
result:: @code
{
mysql
_
stmt
_
store
_
result()
}
* mysql
_
send
_
long
_
data::
* mysql
_
fetch:: @code
{
mysql
_
fetch()
}
* mysql
_
stmt
_
close::
* mysql
_
send
_
long
_
data:: @code
{
mysql
_
send
_
long
_
data()
}
* mysql
_
stmt
_
errno::
* mysql
_
stmt
_
close:: @code
{
mysql
_
stmt
_
close()
}
* mysql
_
stmt
_
error::
* mysql
_
stmt
_
errno:: @code
{
mysql
_
stmt
_
errno()
}
* mysql
_
commit::
* mysql
_
stmt
_
error:: @code
{
mysql
_
stmt
_
error()
}
* mysql
_
rollback::
* mysql
_
commit:: @code
{
mysql
_
commit()
}
* mysql
_
autocommit::
* mysql
_
rollback:: @code
{
mysql
_
rollback()
}
* mysql
_
autocommit:: @code
{
mysql
_
autocommit()
}
* mysql
_
more
_
results:: @code
{
mysql
_
more
_
results()
}
* mysql
_
next
_
result:: @code
{
mysql
_
next
_
result()
}
@end menu
@end menu
@node mysql
_
prepare, mysql
_
param
_
count, C Prepared statement functions, C Prepared statement functions
@node mysql
_
prepare, mysql
_
param
_
count, C Prepared statement functions, C Prepared statement functions
...
@@ -488,6 +520,18 @@ occured.
...
@@ -488,6 +520,18 @@ occured.
@subsubheading Errors
@subsubheading Errors
@item CR
_
COMMANDS
_
OUT
_
OF
_
SYNC
Commands were executed in an improper order
@item CR
_
OUT
_
OF
_
MEMORY
Out of memory
@item CR
_
SERVER
_
GONE
_
ERROR
The MySQL server has gone away
@item CR
_
SERVER
_
LOST
The connection to the server was lost during the query
@item CR
_
UNKNOWN
_
ERROR
An unkown error occured
@end table
If the prepare is not successful, i.e. when @code
{
mysql
_
prepare()
}
returned a
If the prepare is not successful, i.e. when @code
{
mysql
_
prepare()
}
returned a
NULL statement, errors can be obtained by calling @code
{
mysql
_
error()
}
.
NULL statement, errors can be obtained by calling @code
{
mysql
_
error()
}
.
...
@@ -573,6 +617,11 @@ the prepared query.
...
@@ -573,6 +617,11 @@ the prepared query.
@subsubheading Errors
@subsubheading Errors
@item CR
_
OUT
_
OF
_
MEMOR
Out of memory
@item CR
_
UNKNOWN
_
ERROR
An unknown error occured
None
None
...
@@ -612,6 +661,14 @@ MYSQL_TYPE_FLOAT
...
@@ -612,6 +661,14 @@ MYSQL_TYPE_FLOAT
@item
@item
MYSQL
_
TYPE
_
DOUBLE
MYSQL
_
TYPE
_
DOUBLE
@item
@item
MYSQL
_
TYPE
_
TIME
@item
MYSQL
_
TYPE
_
DATE
@item
MYSQL
_
TYPE
_
DATETIME
@item
MYSQL
_
TYPE
_
TIMESTAMP
@item
MYSQL
_
TYPE
_
STRING
MYSQL
_
TYPE
_
STRING
@item
@item
MYSQL
_
TYPE
_
VAR
_
STRING
MYSQL
_
TYPE
_
VAR
_
STRING
...
@@ -639,6 +696,10 @@ buffer type is non string or binary
...
@@ -639,6 +696,10 @@ buffer type is non string or binary
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
The conversion is not supported, possibly the buffer
_
type is illegal or
The conversion is not supported, possibly the buffer
_
type is illegal or
its not from the above list of supported types.
its not from the above list of supported types.
@item CR
_
OUT
_
OF
_
MEMOR
Out of memory
@item CR
_
UNKNOWN
_
ERROR
An unknown error occured
@end table
@end table
@subsubheading Example
@subsubheading Example
...
@@ -678,11 +739,9 @@ how to fetch the statement binary data, refer to @ref{mysql_fetch}.
...
@@ -678,11 +739,9 @@ how to fetch the statement binary data, refer to @ref{mysql_fetch}.
@multitable @columnfractions .30 .65
@multitable @columnfractions .30 .65
@item @strong
{
Return Value
}
@tab @strong
{
Description
}
@item @strong
{
Return Value
}
@tab @strong
{
Description
}
@item
MYSQL
_
SUCCESS, 0 @tab Successful
@item
0 @tab Successful
@item
MYSQL
_
STATUS
_
ERROR, 1 @tab Error occured. Error code and
@item
1 @tab Error occured. Error code and
message can be obtained by calling @code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
.
message can be obtained by calling @code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
.
@item MYSQL
_
NEED
_
DATA, 99 @tab One of the parameter buffer is
indicating the data suppy in chunks, and the supply is not yet complete.
@end multitable
@end multitable
...
@@ -693,10 +752,16 @@ indicating the data suppy in chunks, and the supply is not yet complete.
...
@@ -693,10 +752,16 @@ indicating the data suppy in chunks, and the supply is not yet complete.
No query prepared prior to execution
No query prepared prior to execution
@item CR
_
ALL
_
PARAMS
_
NOT
_
BOUND
@item CR
_
ALL
_
PARAMS
_
NOT
_
BOUND
Not all parameters data is supplied
Not all parameters data is supplied
@item CR
_
COMMANDS
_
OUT
_
OF
_
SYNC
Commands were executed in an improper order.
@item CR
_
OUT
_
OF
_
MEMORY
Out of memory.
@item CR
_
SERVER
_
GONE
_
ERROR
@item CR
_
SERVER
_
GONE
_
ERROR
The MySQL server has gone away
The MySQL server has gone away.
@item CR
_
SERVER
_
LOST
The connection to the server was lost during the query.
@item CR
_
UNKNOWN
_
ERROR
@item CR
_
UNKNOWN
_
ERROR
An unk
own error occured
An unk
nown error occurred.
@end table
@end table
...
@@ -714,7 +779,9 @@ ulonglong affected_rows;
...
@@ -714,7 +779,9 @@ ulonglong affected_rows;
long length;
long length;
unsigned int param
_
count;
unsigned int param
_
count;
int int
_
data;
int int
_
data;
short small
_
data;
char str
_
data[50], query[255];
char str
_
data[50], query[255];
my
_
bool is
_
null;
/* Set autocommit mode to true */
/* Set autocommit mode to true */
mysql
_
autocommit(mysql, 1);
mysql
_
autocommit(mysql, 1);
...
@@ -735,8 +802,8 @@ char str_data[50], query[255];
...
@@ -735,8 +802,8 @@ char str_data[50], query[255];
@
}
@
}
/* Prepare a insert query with 3 parameters */
/* Prepare a insert query with 3 parameters */
str
cpy(query, "INSERT INTO test
_
table(col1,col2,col3) values(?,?,?)");
str
mov(query, "INSERT INTO test
_
table(col1,col2,col3) values(?,?,?)");
if(!(stmt = mysql
_
prepare(mysql,
query,strlen(query))))
if(!(stmt = mysql
_
prepare(mysql,
query, strlen(query))))
@
{
@
{
fprintf(stderr, "
\n
prepare, insert failed");
fprintf(stderr, "
\n
prepare, insert failed");
fprintf(stderr, "
\n
%s", mysql_error(mysql));
fprintf(stderr, "
\n
%s", mysql_error(mysql));
...
@@ -757,19 +824,25 @@ char str_data[50], query[255];
...
@@ -757,19 +824,25 @@ char str_data[50], query[255];
/* Bind the data for the parameters */
/* Bind the data for the parameters */
/* INTEGER PART */
/* INTEGER PART */
memset(bind,0,sizeof(bind));
bind[0].buffer
_
type= MYSQL
_
TYPE
_
LONG;
bind[0].buffer
_
type= MYSQL
_
TYPE
_
LONG;
bind[0].buffer= (void *)
&
int
_
data;
bind[0].buffer= (char *)
&
int
_
data;
bind[0].is
_
null= 0;
bind[0].length= 0;
/* STRING PART */
/* STRING PART */
bind[1].buffer
_
type= MYSQL
_
TYPE
_
VAR
_
STRING;
bind[1].buffer
_
type= MYSQL
_
TYPE
_
VAR
_
STRING;
bind[1].buffer= (
void *)str
_
data;
bind[1].buffer= (
char *)str
_
data;
bind[1].buffer
_
length= sizeof(str
_
data);
bind[1].buffer
_
length= sizeof(str
_
data);
bind[1].is
_
null= 0;
bind[1].length= 0;
/* SMALLINT PART */
/* SMALLINT PART */
bind[2].buffer
_
type= MYSQL
_
TYPE
_
SHORT;
bind[2].buffer
_
type= MYSQL
_
TYPE
_
SHORT;
bind[2].buffer= (void *)
&
small
_
data;
bind[2].buffer= (char *)
&
small
_
data;
bind[2].length= (long *)
&
length;
bind[2].is
_
null=
&
is
_
null;
bind[2].length= 0;
is
_
null= 0;
/* Bind the buffers */
/* Bind the buffers */
if (mysql
_
bind
_
param(stmt, bind))
if (mysql
_
bind
_
param(stmt, bind))
...
@@ -782,8 +855,9 @@ char str_data[50], query[255];
...
@@ -782,8 +855,9 @@ char str_data[50], query[255];
/* Specify the data */
/* Specify the data */
int
_
data= 10; /* integer */
int
_
data= 10; /* integer */
strcpy(str
_
data,"MySQL"); /* string */
strcpy(str
_
data,"MySQL"); /* string */
/* INSERT SMALLINT data as NULL */
/* INSERT SMALLINT data as NULL */
length= MYSQL
_
NULL
_
DATA;
is
_
null= 1;
/* Execute the insert statement - 1*/
/* Execute the insert statement - 1*/
if (mysql
_
execute(stmt))
if (mysql
_
execute(stmt))
...
@@ -808,7 +882,7 @@ char str_data[50], query[255];
...
@@ -808,7 +882,7 @@ char str_data[50], query[255];
int
_
data= 1000;
int
_
data= 1000;
strcpy(str
_
data,"The most popular open source database");
strcpy(str
_
data,"The most popular open source database");
small
_
data= 1000; /* smallint */
small
_
data= 1000; /* smallint */
length= 0;
is
_
null= 0; /* reset NULL */
/* Execute the insert statement - 2*/
/* Execute the insert statement - 2*/
if (mysql
_
execute(stmt))
if (mysql
_
execute(stmt))
...
@@ -843,7 +917,7 @@ char str_data[50], query[255];
...
@@ -843,7 +917,7 @@ char str_data[50], query[255];
fprintf(stderr, "
\n
%s", mysql_error(mysql));
fprintf(stderr, "
\n
%s", mysql_error(mysql));
exit(0);
exit(0);
@
}
@
}
fprintf(stdout, "Success, MySQL prepared statements are working
great !!!");
fprintf(stdout, "Success, MySQL prepared statements are working
!!!");
@end example
@end example
...
@@ -885,7 +959,7 @@ from @ref{mysql_execute,mysql_execute()}.
...
@@ -885,7 +959,7 @@ from @ref{mysql_execute,mysql_execute()}.
@node mysql
_
bind
_
result, mysql
_
fetch, mysql
_
stmt
_
affected
_
rows, C Prepared statement functions
@node mysql
_
bind
_
result, mysql
_
stmt
_
store
_
result, mysql
_
stmt
_
affected
_
rows, C Prepared statement functions
@subsubsection @code
{
mysql
_
bind
_
result()
}
@subsubsection @code
{
mysql
_
bind
_
result()
}
@findex @code
{
mysql
_
bind
_
result()
}
@findex @code
{
mysql
_
bind
_
result()
}
...
@@ -894,7 +968,7 @@ from @ref{mysql_execute,mysql_execute()}.
...
@@ -894,7 +968,7 @@ from @ref{mysql_execute,mysql_execute()}.
@subsubheading Description
@subsubheading Description
@code
{
mysql
_
bind
_
result()
}
is
ised to associate, or bind, columns in the
@code
{
mysql
_
bind
_
result()
}
is
used to associate, or bind, columns in the
resultset to data buffers and length buffers. When @code
{
mysql
_
fetch()
}
is
resultset to data buffers and length buffers. When @code
{
mysql
_
fetch()
}
is
called to fetch data, the MySQL client protocol returns the data for the
called to fetch data, the MySQL client protocol returns the data for the
bound columns in the specified buffers.
bound columns in the specified buffers.
...
@@ -938,6 +1012,14 @@ MYSQL_TYPE_FLOAT
...
@@ -938,6 +1012,14 @@ MYSQL_TYPE_FLOAT
@item
@item
MYSQL
_
TYPE
_
DOUBLE
MYSQL
_
TYPE
_
DOUBLE
@item
@item
MYSQL
_
TYPE
_
TIME
@item
MYSQL
_
TYPE
_
DATE
@item
MYSQL
_
TYPE
_
DATETIME
@item
MYSQL
_
TYPE
_
TIMESTAMP
@item
MYSQL
_
TYPE
_
STRING
MYSQL
_
TYPE
_
STRING
@item
@item
MYSQL
_
TYPE
_
VAR
_
STRING
MYSQL
_
TYPE
_
VAR
_
STRING
...
@@ -956,12 +1038,17 @@ MYSQL_TYPE_LONG_BLOB
...
@@ -956,12 +1038,17 @@ MYSQL_TYPE_LONG_BLOB
Zero if the bind was successful. Non-zero if an error occured.
Zero if the bind was successful. Non-zero if an error occured.
@subsubheading Errors
@subsubheading Errors
@table @code
@table @code
@item CR
_
NO
_
PREPARE
_
STMT
@item CR
_
NO
_
PREPARE
_
STMT
No prepared statement exists
No prepared statement exists
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
The conversion is not supported, possibly the buffer
_
type is illegal or
The conversion is not supported, possibly the buffer
_
type is illegal or
its not from the list of supported types.
its not from the list of supported types.
@item CR
_
OUT
_
OF
_
MEMOR
Out of memory
@item CR
_
UNKNOWN
_
ERROR
An unknown error occured
@end table
@end table
@subsubheading Example
@subsubheading Example
...
@@ -971,7 +1058,53 @@ For the usage of @code{mysql_bind_result()} refer to the Example from
...
@@ -971,7 +1058,53 @@ For the usage of @code{mysql_bind_result()} refer to the Example from
@node mysql
_
fetch, mysql
_
send
_
long
_
data, mysql
_
bind
_
result, C Prepared statement functions
@node mysql
_
stmt
_
store
_
result, mysql
_
fetch, mysql
_
bind
_
result, C Prepared statement functions
@subsubsection @code
{
mysql
_
stmt
_
store
_
result()
}
@findex code
{
mysql
_
stmt
_
store
_
result()
}
@code
{
int mysql
_
stmt
_
store
_
result(MYSQL
_
STMT *stmt)
}
@subsubheading Description
You must call @code
{
mysql
_
stmt
_
store
_
result()
}
for every query that
successfully retrieves
data(@code
{
SELECT
}
,@code
{
SHOW
}
,@code
{
DESCRIBE
}
,@code
{
EXPLAIN
}
), and only
if you want to buffer the complete result set by the client, so that the
subsequent @code
{
mysql
_
fetch()
}
call returns buffered data.
@sp 1
You don't have to call @code
{
mysql
_
stmt
_
store
_
result()
}
for other
queries, but it will not harm or cause any notable performance in all
cases.You can detect if the query didn't have a result set by checking
if @code
{
mysql
_
prepare
_
result()
}
returns 0. For more information refer
to @ref
{
mysql
_
prepare
_
result
}
.
@subsubheading Return Values
@code
{
Zero
}
if the results are buffered successfully or @code
{
Non Zero
}
in case of an error.
@subsubheading Errors
@table @code
@item CR
_
COMMANDS
_
OUT
_
OF
_
SYNC
Commands were executed in an improper order.
@item CR
_
OUT
_
OF
_
MEMORY
Out of memory.
@item CR
_
SERVER
_
GONE
_
ERROR
The MySQL server has gone away.
@item CR
_
SERVER
_
LOST
The connection to the server was lost during the query.
@item CR
_
UNKNOWN
_
ERROR
An unknown error occurred.
@end table
@node mysql
_
fetch, mysql
_
send
_
long
_
data, mysql
_
stmt
_
store
_
result, C Prepared statement functions
@subsubsection @code
{
mysql
_
fetch()
}
@subsubsection @code
{
mysql
_
fetch()
}
@findex code
{
mysql
_
fetch()
}
@findex code
{
mysql
_
fetch()
}
...
@@ -982,7 +1115,9 @@ For the usage of @code{mysql_bind_result()} refer to the Example from
...
@@ -982,7 +1115,9 @@ For the usage of @code{mysql_bind_result()} refer to the Example from
@code
{
mysql
_
fetch()
}
returns the next rowset in the result set. It can
@code
{
mysql
_
fetch()
}
returns the next rowset in the result set. It can
be called only while the result set exists i.e. after a call to
be called only while the result set exists i.e. after a call to
@code
{
mysql
_
execute()
}
that creates a result set.
@code
{
mysql
_
execute()
}
that creates a result set or after
@code
{
mysql
_
stmt
_
store
_
result()
}
, which is called after
@code
{
mysql
_
execute()
}
to buffer the entire resultset.
@sp 1
@sp 1
...
@@ -994,11 +1129,12 @@ set and the lengths are returned to the length pointer.
...
@@ -994,11 +1129,12 @@ set and the lengths are returned to the length pointer.
Note that, all columns must be bound by the application.
Note that, all columns must be bound by the application.
@sp 1
@sp 1
If the data fetched is a NULL data, then the length buffer will have a
If the data fetched is a NULL data, then the @code
{
is
_
null
}
value from
value of @strong
{
MYSQL
_
NULL
_
DATA
}
, -1, else it will have the length of
@code
{
MYSQL
_
BIND
}
contains TRUE, 1, else the data and its length is
the data being fetched based on the buffer type specified by the
returned to @code
{
*buffer
}
and @code
{
*length
}
variables based on the
application. All numeric, float and double types have the
buffer type specified by the application. All numeric, float and double
fixed length(in bytes) as listed below:
types have the fixed length(in bytes) as listed below:
@multitable @columnfractions .10 .30
@multitable @columnfractions .10 .30
@item @strong
{
Type
}
@tab @strong
{
Length
}
@item @strong
{
Type
}
@tab @strong
{
Length
}
...
@@ -1008,6 +1144,10 @@ fixed length(in bytes) as listed below:
...
@@ -1008,6 +1144,10 @@ fixed length(in bytes) as listed below:
@item MYSQL
_
TYPE
_
FLOAT @tab 4
@item MYSQL
_
TYPE
_
FLOAT @tab 4
@item MYSQL
_
TYPE
_
LONGLONG @tab 8
@item MYSQL
_
TYPE
_
LONGLONG @tab 8
@item MYSQL
_
TYPE
_
DOUBLE @tab 8
@item MYSQL
_
TYPE
_
DOUBLE @tab 8
@item MYSQL
_
TYPE
_
TIME @tab sizeof(MYSQL
_
TIME)
@item MYSQL
_
TYPE
_
DATE @tab sizeof(MYSQL
_
TIME)
@item MYSQL
_
TYPE
_
DATETIME @tab sizeof(MYSQL
_
TIME)
@item MYSQL
_
TYPE
_
TIMESTAMP @tab sizeof(MYSQL
_
TIME)
@item MYSQL
_
TYPE
_
STRING @tab data length
@item MYSQL
_
TYPE
_
STRING @tab data length
@item MYSQL
_
TYPE
_
VAR
_
STRING @tab data
_
length
@item MYSQL
_
TYPE
_
VAR
_
STRING @tab data
_
length
@item MYSQL
_
TYPE
_
BLOB @tab data
_
length
@item MYSQL
_
TYPE
_
BLOB @tab data
_
length
...
@@ -1023,21 +1163,31 @@ where @code{*data_length} is nothing but the 'Actual length of the data'.
...
@@ -1023,21 +1163,31 @@ where @code{*data_length} is nothing but the 'Actual length of the data'.
@multitable @columnfractions .30 .65
@multitable @columnfractions .30 .65
@item @strong
{
Return Value
}
@tab @strong
{
Description
}
@item @strong
{
Return Value
}
@tab @strong
{
Description
}
@item
MYSQL
_
SUCCESS, 0 @tab Successful, the data has been
@item
0 @tab Successful, the data has been
fetched to application data buffers.
fetched to application data buffers.
@item
MYSQL
_
STATUS
_
ERROR, 1 @tab Error occured. Error code and
@item
1 @tab Error occured. Error code and
message can be obtained by calling @code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
.
message can be obtained by calling @code
{
mysql
_
stmt
_
errno()
}
and @code
{
mysql
_
stmt
_
error()
}
.
@item
MYSQL
_
NO
_
DATA, 100 @tab No more rows/data exists
@item
100, MYSQL
_
NO
_
DATA @tab No more rows/data exists
@end multitable
@end multitable
@subsubheading Errors
@subsubheading Errors
@table @code
@table @code
@item CR
_
COMMANDS
_
OUT
_
OF
_
SYNC
Commands were executed in an improper order.
@item CR
_
OUT
_
OF
_
MEMORY
Out of memory.
@item CR
_
SERVER
_
GONE
_
ERROR
The MySQL server has gone away.
@item CR
_
SERVER
_
LOST
The connection to the server was lost during the query.
@item CR
_
UNKNOWN
_
ERROR
An unknown error occurred.
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
@item CR
_
UNSUPPORTED
_
PARAM
_
TYPE
If the
field type is DATE,DATETIME,TIME,or TIMESTAMP; and the
If the
buffer type is MYSQL
_
TYPE
_
DATE,DATETIME,TIME,or TIMESTAMP; and if
application buffer type is non string based.
the field type is not DATE, TIME, DATETIME or TIMESTAMP.
@item
@item
All other un
-supported conversions are returned from
All other un
supported conversion errors are returned from
@code
{
mysql
_
bind
_
result()
}
.
@code
{
mysql
_
bind
_
result()
}
.
@end table
@end table
...
@@ -1054,6 +1204,7 @@ MYSQL_RES *result;
...
@@ -1054,6 +1204,7 @@ MYSQL_RES *result;
int int
_
data;
int int
_
data;
long int
_
length, str
_
length;
long int
_
length, str
_
length;
char str
_
data[50];
char str
_
data[50];
my
_
bool is
_
null[2];
query= "SELECT col1, col2 FROM test
_
table WHERE col1= 10)");
query= "SELECT col1, col2 FROM test
_
table WHERE col1= 10)");
if (!(stmt= mysql
_
prepare(
&
mysql, query, strlen(query)))
if (!(stmt= mysql
_
prepare(
&
mysql, query, strlen(query)))
...
@@ -1082,19 +1233,20 @@ char str_data[50];
...
@@ -1082,19 +1233,20 @@ char str_data[50];
/* Execute the SELECT query */
/* Execute the SELECT query */
if (mysql
_
execute(stmt))
if (mysql
_
execute(stmt))
@
{
@
{
fprintf(stderr, "
\n
execute didn't retuned expected return code, MYSQL
_
NEED
_
DATA");
fprintf(stderr, "
\n
execute failed");
fprintf(stderr, "
\n
%s", mysql_stmt_error(stmt));
exit(0);
exit(0);
@
}
@
}
/* Bind the result data buffers */
/* Bind the result data buffers */
bzero(bind, 0, sizeof(bind));
bind[0].buffer
_
type= MYSQL
_
TYPE
_
LONG;
bind[0].buffer
_
type= MYSQL
_
TYPE
_
LONG;
bind[0].buffer= (void *)
&
int
_
data;
bind[0].buffer= (char *)
&
int
_
data;
bind[0].is
_
null=
&
is
_
null[0];
bind[0].length=
&
int
_
length;
bind[0].length=
&
int
_
length;
bind[1].buffer
_
type= MYSQL
_
TYPE
_
VAR
_
STRING;
bind[1].buffer
_
type= MYSQL
_
TYPE
_
VAR
_
STRING;
bind[1].buffer= (void *)str
_
data;
bind[1].buffer= (void *)str
_
data;
bind[1].is
_
null=
&
is
_
null[1];
bind[1].length=
&
str
_
length;
bind[1].length=
&
str
_
length;
if (mysql
_
bind
_
result(stmt, bind))
if (mysql
_
bind
_
result(stmt, bind))
...
@@ -1112,8 +1264,16 @@ char str_data[50];
...
@@ -1112,8 +1264,16 @@ char str_data[50];
exit(0);
exit(0);
@
}
@
}
fprintf(stdout, "
\n
int
_
data:
%d, length: %ld", int_data, int_length);
if (is
_
null[0])
fprintf(stdout, "
\n
str
_
data:
%s, length: %ld", str_data, str_length);
fprintf(stdout, "
\n
Col1 data is NULL");
else
fprintf(stdout, "
\n
Col1:
%d, length: %ld", int_data, int_length);
if (is
_
null[1])
fprintf(stdout, "
\n
Col2 data is NULL");
else
fprintf(stdout, "
\n
Col2:
%s, length: %ld", str_data, str_length);
/* call mysql
_
fetch again */
/* call mysql
_
fetch again */
if (mysql
_
fetch(stmt) |= MYSQL
_
NO
_
DATA)
if (mysql
_
fetch(stmt) |= MYSQL
_
NO
_
DATA)
...
@@ -1122,7 +1282,7 @@ char str_data[50];
...
@@ -1122,7 +1282,7 @@ char str_data[50];
exit(0);
exit(0);
@
}
@
}
/* Free the prepare result
*/
/* Free the prepare result
meta information */
mysql
_
free
_
result(result);
mysql
_
free
_
result(result);
/* Free the statement handle */
/* Free the statement handle */
...
@@ -1144,7 +1304,7 @@ char str_data[50];
...
@@ -1144,7 +1304,7 @@ char str_data[50];
@findex @code
{
mysql
_
send
_
long
_
data()
}
.
@findex @code
{
mysql
_
send
_
long
_
data()
}
.
@code
{
int mysql
_
send
_
long
_
data(MYSQL
_
STMT *stmt, unsigned int
@code
{
int mysql
_
send
_
long
_
data(MYSQL
_
STMT *stmt, unsigned int
parameter
_
number, const char *data, ulong length
, my
_
bool is
_
last
_
data)
}
parameter
_
number, const char *data, ulong length
)
}
@subsubheading Description
@subsubheading Description
...
@@ -1156,13 +1316,7 @@ binary data type.
...
@@ -1156,13 +1316,7 @@ binary data type.
@sp 1
@sp 1
The @code
{
data
}
is a pointer to buffer containing the actual data for
The @code
{
data
}
is a pointer to buffer containing the actual data for
the parameter represendted by @code
{
parameter
_
number
}
. The @code
{
length
}
the parameter represendted by @code
{
parameter
_
number
}
. The @code
{
length
}
indicates the amount of data to be sent in bytes, and @code
{
is
_
last
_
data
}
is a
indicates the amount of data to be sent in bytes.
boolean flag to indicate the end of the data. If it is != 0, then the
current call will be the end of the data, else it waits for the
application to send all data. If the application doesn't ended the data
supply from @code
{
mysql
_
send
_
long
_
data()
}
, then the
@code
{
mysql
_
execute()
}
will return @strong
{
MYSQL
_
NEED
_
DATA
}
.
@subsubheading Return Values
@subsubheading Return Values
...
@@ -1176,10 +1330,14 @@ occured.
...
@@ -1176,10 +1330,14 @@ occured.
@table @code
@table @code
@item CR
_
INVALID
_
PARAMETER
_
NO
@item CR
_
INVALID
_
PARAMETER
_
NO
Invalid parameter number
Invalid parameter number
@item CR
_
COMMANDS
_
OUT
_
OF
_
SYNC
Commands were executed in an improper order.
@item CR
_
SERVER
_
GONE
_
ERROR
@item CR
_
SERVER
_
GONE
_
ERROR
The MySQL server has gone away
The MySQL server has gone away
@item CR
_
OUT
_
OF
_
MEMOR
Out of memory
@item CR
_
UNKNOWN
_
ERROR
@item CR
_
UNKNOWN
_
ERROR
An unk
own error occured
An unk
nown error occured
@end table
@end table
@subsubheading Example
@subsubheading Example
...
@@ -1200,9 +1358,7 @@ long length;
...
@@ -1200,9 +1358,7 @@ long length;
memset(bind, 0, sizeof(bind));
memset(bind, 0, sizeof(bind));
bind[0].buffer
_
type= MYSQL
_
TYPE
_
STRING;
bind[0].buffer
_
type= MYSQL
_
TYPE
_
STRING;
bind[0].length=
&
length;
bind[0].length=
&
length;
bind[0].is
_
null= 0;
/* Indicate that the data supply is in CHUNKS */
length= MYSQL
_
LONG
_
DATA;
/* Bind the buffers */
/* Bind the buffers */
if (mysql
_
bind
_
param(stmt, bind))
if (mysql
_
bind
_
param(stmt, bind))
...
@@ -1212,22 +1368,16 @@ long length;
...
@@ -1212,22 +1368,16 @@ long length;
exit(0);
exit(0);
@
}
@
}
/* Execute the insert statement - It should return MYSQL
_
NEED
_
DATA */
if (mysql
_
execute(stmt) != MYSQL
_
NEED
_
DATA)
@
{
fprintf(stderr, "
\n
execute didn't retuned expected return code, MYSQL
_
NEED
_
DATA");
exit(0);
@
}
/* Supply data in chunks to server */
/* Supply data in chunks to server */
if (!mysql
_
send
_
long
_
data(stmt,1,"MySQL",5
,0))
if (!mysql
_
send
_
long
_
data(stmt,1,"MySQL",5
))
@
{
@
{
fprintf(stderr, "
\n
send
_
long
_
data failed");
fprintf(stderr, "
\n
send
_
long
_
data failed");
fprintf(stderr, "
\n
%s", mysql_stmt_error(stmt));
fprintf(stderr, "
\n
%s", mysql_stmt_error(stmt));
exit(0);
exit(0);
@
}
@
}
/* Supply the last piece of data */
if (mysql
_
send
_
long
_
data(stmt,1," - The most popular open source database",40,1))
/* Supply the next piece of data */
if (mysql
_
send
_
long
_
data(stmt,1," - The most popular open source database",40))
@
{
@
{
fprintf(stderr, "
\n
send
_
long
_
data failed");
fprintf(stderr, "
\n
send
_
long
_
data failed");
fprintf(stderr, "
\n
%s", mysql_stmt_error(stmt));
fprintf(stderr, "
\n
%s", mysql_stmt_error(stmt));
...
@@ -1260,6 +1410,9 @@ long length;
...
@@ -1260,6 +1410,9 @@ long length;
Closes the prepared statement. @code
{
mysql
_
stmt
_
close()
}
also
Closes the prepared statement. @code
{
mysql
_
stmt
_
close()
}
also
deallocates the statement handle pointed to by @code
{
stmt
}
.
deallocates the statement handle pointed to by @code
{
stmt
}
.
If the current query results are pending or un-read; this cancels the
query results; so that next call can be executed.
@subsubheading Return Values
@subsubheading Return Values
Zero if the statement was freed successfully. Non-zero if an error occured.
Zero if the statement was freed successfully. Non-zero if an error occured.
...
@@ -1398,7 +1551,7 @@ None.
...
@@ -1398,7 +1551,7 @@ None.
@node mysql
_
autocommit,
, mysql
_
rollback, C Prepared statement functions
@node mysql
_
autocommit,
mysql
_
more
_
results, mysql
_
rollback, C Prepared statement functions
@subsubsection @code
{
mysql
_
autocommit()
}
@subsubsection @code
{
mysql
_
autocommit()
}
...
@@ -1419,4 +1572,165 @@ Zero if successful. Non-zero if an error occured
...
@@ -1419,4 +1572,165 @@ Zero if successful. Non-zero if an error occured
None.
None.
@node mysql
_
more
_
results, mysql
_
next
_
result, mysql
_
autocommit, C Prepared statement functions
@subsubsection @code
{
mysql
_
more
_
results()
}
@findex @code
{
mysql
_
more
_
results()
}
.
@code
{
my
_
bool mysql
_
more
_
results(MYSQL *mysql)
}
@subsubheading Description
Returns true if more results exists from the currently executed query,
and the application must call @code
{
mysql
_
next
_
result()
}
to fetch the
results.
@subsubheading Return Values
@code
{
TRUE
}
if more results exists. @code
{
FALSE
}
if no more results exists.
@subsubheading Errors
None.
@node mysql
_
next
_
result, , mysql
_
more
_
results, C Prepared statement functions
@subsubsection @code
{
mysql
_
next
_
result()
}
@findex @code
{
mysql
_
next
_
result()
}
.
@code
{
int mysql
_
next
_
result(MYSQL *mysql)
}
@subsubheading Description
If more query results exists, then @code
{
mysql
_
next
_
result()
}
reads the
next query results and returns the status back to application.
@subsubheading Return Values
Zero if successful. Non-zero if an error occured
@subsubheading Errors
None.
@node multiple queries, date handling, C Prepared statement functions, MySQL prepared statements
@subsection Handling multiple query executions
From version 4.1 and above, MySQL supports the multi query execution
using the single command. In order to do this, you must set the client flag
@code
{
CLIENT
_
MULTI
_
QUERIES
}
option during the connection.
@sp 1
By default @code
{
mysql
_
query()
}
or @code
{
mysql
_
real
_
query()
}
returns
only the first query status and the subsequent queries status can
be processed using @code
{
mysql
_
more
_
results()
}
and
@code
{
mysql
_
next
_
result()
}
.
@example
/* Connect to server with option CLIENT
_
MULTI
_
QUERIES */
mysql
_
real
_
query(..., CLIENT
_
MULTI
_
QUERIES);
/* Now execute multiple queries */
mysql
_
query(mysql,"DROP TABLE IF EXISTS test
_
table;
\
CREATE TABLE test
_
table(id int);
\
INSERT INTO test
_
table VALUES(10);
\
UPDATE test
_
table SET id=20 WHERE id=10;
\
SELECT * FROM test
_
table;
\
DROP TABLE test
_
table";
while (mysql
_
more
_
results(mysql))
{
/* Process all results */
mysql
_
next
_
result(mysql);
...
printf("total affected rows:
%lld", mysql_affected_rows(mysql));
...
if ((result= mysql
_
store
_
result(mysql))
{
/* Returned a result set, process it */
}
}
@end example
@node date handling, , multiple queries, MySQL prepared statements
@subsection Handling DATE, TIME and TIMESTAMP
Using the new binary protocol from MySQL 4.1 and above, one can send and
receive the DATE, TIME and TIMESTAMP data using the @code
{
MYSQL
_
TIME
}
structure.
@code
{
MYSQL
_
TIME
}
structure consites of the following members:
@itemize @bullet
@item year
@item month
@item day
@item hour
@item minute
@item second
@item second
_
part
@end itemize
In order to send the data, one must use the prepared statements through
@code
{
mysql
_
prepare()
}
and @code
{
mysql
_
execute()
}
; and must bind the
parameter using type as @code
{
MYSQL
_
TYPE
_
DATE
}
inorder to process date
value, @code
{
MYSQL
_
TYPE
_
TIME
}
for time and @code
{
MYSQL
_
TYPE
_
DATETIME
}
or
@code
{
MYSQL
_
TYPE
_
TIMESTAMP
}
for datetime/timestamp using
@code
{
mysql
_
bind
_
param()
}
when sending and @code
{
mysql
_
bind
_
results()
}
while receiving the data.
@sp 1
Here is a simple example; which inserts the DATE, TIME and TIMESTAMP data.
@example
MYSQL
_
TIME ts;
MYSQL
_
BIND bind[3];
MYSQL
_
STMT *stmt;
strmov(query, "INSERT INTO test
_
table(date
_
field, time
_
field,
timestamp
_
field) VALUES(?,?,?");
stmt= mysql
_
prepare(mysql, query, strlen(query)));
/* setup input buffers for all 3 parameters */
bind[0].buffer
_
type= MYSQL
_
TYPE
_
DATE;
bind[0].buffer= (char *)
&
ts;
bind[0].is
_
null= 0;
bind[0].length= 0;
..
bind[1]= bind[2]= bind[0];
..
mysql
_
bind
_
param(stmt, bind);
/* supply the data to be sent is the ts structure */
ts.year= 2002;
ts.month= 02;
ts.day= 03;
ts.hour= 10;
ts.minute= 45;
ts.second= 20;
mysql
_
execute(stmt);
..
@end example
@bye
@bye
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment