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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
ed8b2529
Commit
ed8b2529
authored
Oct 16, 2002
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
some fixes for SELECT INTO @vars ..
sql/sql_parse.cc: Simplification of code
parent
ce37f3ab
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
118 additions
and
105 deletions
+118
-105
sql/sql_class.cc
sql/sql_class.cc
+24
-14
sql/sql_class.h
sql/sql_class.h
+5
-15
sql/sql_lex.h
sql/sql_lex.h
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+12
-39
sql/sql_yacc.yy
sql/sql_yacc.yy
+76
-36
No files found.
sql/sql_class.cc
View file @
ed8b2529
...
@@ -916,31 +916,41 @@ bool select_exists_subselect::send_data(List<Item> &items)
...
@@ -916,31 +916,41 @@ bool select_exists_subselect::send_data(List<Item> &items)
/***************************************************************************
/***************************************************************************
** Dump of select to variables
** Dump of select to variables
***************************************************************************/
***************************************************************************/
int
select_dumpvar
::
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
bool
select_dumpvar
::
send_data
(
List
<
Item
>
&
items
)
{
{
List_iterator_fast
<
Item
>
li
(
items
);
List_iterator_fast
<
Item
>
li
(
list
);
List_iterator_fast
<
LEX_STRING
>
gl
(
current_thd
->
lex
.
select_into_
var_list
);
List_iterator_fast
<
LEX_STRING
>
gl
(
var_list
);
Item
*
item
;
Item
*
item
;
LEX_STRING
*
ls
;
LEX_STRING
*
ls
;
DBUG_ENTER
(
"send_data"
);
if
(
var_list
.
elements
!=
list
.
elements
)
if
(
row_count
++
>
1
)
{
{
my_error
(
ER_
TOO_MANY_ROWS
,
MYF
(
0
));
my_error
(
ER_
WRONG_NUMBER_OF_COLUMNS_IN_SELECT
,
MYF
(
0
));
goto
err
;
return
1
;
}
}
while
((
item
=
li
++
)
&&
(
ls
=
gl
++
)
)
while
((
item
=
li
++
))
{
{
ls
=
gl
++
;
Item_func_set_user_var
*
xx
=
new
Item_func_set_user_var
(
*
ls
,
item
);
Item_func_set_user_var
*
xx
=
new
Item_func_set_user_var
(
*
ls
,
item
);
xx
->
fix_fields
(
current_thd
,(
TABLE_LIST
*
)
current_thd
->
lex
.
select_lex
.
table_list
.
first
,
&
item
);
xx
->
fix_fields
(
current_thd
,(
TABLE_LIST
*
)
current_thd
->
lex
.
select_lex
.
table_list
.
first
,
&
item
);
xx
->
fix_length_and_dec
();
xx
->
fix_length_and_dec
();
xx
->
update
(
);
vars
.
push_back
(
xx
);
}
}
DBUG_RETURN
(
0
);
return
0
;
err:
}
bool
select_dumpvar
::
send_data
(
List
<
Item
>
&
items
)
{
List_iterator_fast
<
Item_func_set_user_var
>
li
(
vars
);
Item_func_set_user_var
*
xx
;
DBUG_ENTER
(
"send_data"
);
if
(
row_count
++
)
{
my_error
(
ER_TOO_MANY_ROWS
,
MYF
(
0
));
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
}
while
((
xx
=
li
++
))
xx
->
update
();
DBUG_RETURN
(
0
);
}
}
bool
select_dumpvar
::
send_eof
()
bool
select_dumpvar
::
send_eof
()
...
...
sql/sql_class.h
View file @
ed8b2529
...
@@ -969,22 +969,12 @@ class Unique :public Sql_alloc
...
@@ -969,22 +969,12 @@ class Unique :public Sql_alloc
class
select_dumpvar
:
public
select_result
{
class
select_dumpvar
:
public
select_result
{
ha_rows
row_count
;
ha_rows
row_count
;
public:
public:
select_dumpvar
(
void
)
{
row_count
=
0
;}
List
<
LEX_STRING
>
var_list
;
List
<
Item_func_set_user_var
>
vars
;
select_dumpvar
(
void
)
{
var_list
.
empty
();
vars
.
empty
();
row_count
=
0
;}
~
select_dumpvar
()
{}
~
select_dumpvar
()
{}
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
{
return
0
;}
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;}
{
if
(
current_thd
->
lex
.
select_into_var_list
.
elements
!=
list
.
elements
)
{
my_error
(
ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
,
MYF
(
0
));
return
1
;
}
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
bool
send_data
(
List
<
Item
>
&
items
);
void
send_error
(
uint
errcode
,
const
char
*
err
)
{
my_message
(
errcode
,
err
,
MYF
(
0
));
}
bool
send_eof
();
bool
send_eof
();
};
};
sql/sql_lex.h
View file @
ed8b2529
...
@@ -334,6 +334,7 @@ typedef struct st_lex
...
@@ -334,6 +334,7 @@ typedef struct st_lex
enum
SSL_type
ssl_type
;
/* defined in violite.h */
enum
SSL_type
ssl_type
;
/* defined in violite.h */
String
*
wild
;
String
*
wild
;
sql_exchange
*
exchange
;
sql_exchange
*
exchange
;
select_result
*
result
;
List
<
key_part_spec
>
col_list
;
List
<
key_part_spec
>
col_list
;
List
<
key_part_spec
>
ref_list
;
List
<
key_part_spec
>
ref_list
;
...
@@ -348,7 +349,6 @@ typedef struct st_lex
...
@@ -348,7 +349,6 @@ typedef struct st_lex
List
<
List_item
>
many_values
;
List
<
List_item
>
many_values
;
List
<
set_var_base
>
var_list
;
List
<
set_var_base
>
var_list
;
List
<
Item
>
param_list
;
List
<
Item
>
param_list
;
List
<
LEX_STRING
>
select_into_var_list
;
SQL_LIST
proc_list
,
auxilliary_table_list
;
SQL_LIST
proc_list
,
auxilliary_table_list
;
TYPELIB
*
interval
;
TYPELIB
*
interval
;
create_field
*
last_field
;
create_field
*
last_field
;
...
...
sql/sql_parse.cc
View file @
ed8b2529
...
@@ -1403,7 +1403,7 @@ mysql_execute_command(THD *thd)
...
@@ -1403,7 +1403,7 @@ mysql_execute_command(THD *thd)
switch
(
lex
->
sql_command
)
{
switch
(
lex
->
sql_command
)
{
case
SQLCOM_SELECT
:
case
SQLCOM_SELECT
:
{
{
select_result
*
result
;
select_result
*
result
=
lex
->
result
;
if
(
select_lex
->
options
&
SELECT_DESCRIBE
)
if
(
select_lex
->
options
&
SELECT_DESCRIBE
)
lex
->
exchange
=
0
;
lex
->
exchange
=
0
;
if
(
tables
)
if
(
tables
)
...
@@ -1430,36 +1430,20 @@ mysql_execute_command(THD *thd)
...
@@ -1430,36 +1430,20 @@ mysql_execute_command(THD *thd)
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
lex
->
exchange
)
if
(
!
result
)
{
if
(
lex
->
exchange
->
dumpfile
)
{
if
(
!
(
result
=
new
select_dump
(
lex
->
exchange
)))
{
res
=
-
1
;
break
;
}
}
else
{
if
(
!
(
result
=
new
select_export
(
lex
->
exchange
)))
{
{
res
=
-
1
;
if
((
result
=
new
select_send
()))
break
;
}
}
}
else
if
(
lex
->
select_into_var_list
.
elements
)
{
{
if
(
!
(
result
=
new
select_dumpvar
()))
/*
{
Normal select:
res
=
-
1
;
Change lock if we are using SELECT HIGH PRIORITY,
break
;
FOR UPDATE or IN SHARE MODE
}
*/
TABLE_LIST
*
table
;
for
(
table
=
tables
;
table
;
table
=
table
->
next
)
table
->
lock_type
=
lex
->
lock_option
;
}
}
else
else
{
if
(
!
(
result
=
new
select_send
()))
{
{
res
=
-
1
;
res
=
-
1
;
#ifdef DELETE_ITEMS
#ifdef DELETE_ITEMS
...
@@ -1468,17 +1452,6 @@ mysql_execute_command(THD *thd)
...
@@ -1468,17 +1452,6 @@ mysql_execute_command(THD *thd)
#endif
#endif
break
;
break
;
}
}
else
{
/*
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
*/
TABLE_LIST
*
table
;
for
(
table
=
tables
;
table
;
table
=
table
->
next
)
table
->
lock_type
=
lex
->
lock_option
;
}
}
}
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
tables
)))
if
(
!
(
res
=
open_and_lock_tables
(
thd
,
tables
)))
...
@@ -2976,8 +2949,8 @@ mysql_init_select(LEX *lex)
...
@@ -2976,8 +2949,8 @@ mysql_init_select(LEX *lex)
lex
->
thd
->
variables
.
select_limit
;
lex
->
thd
->
variables
.
select_limit
;
select_lex
->
olap
=
UNSPECIFIED_OLAP_TYPE
;
select_lex
->
olap
=
UNSPECIFIED_OLAP_TYPE
;
lex
->
exchange
=
0
;
lex
->
exchange
=
0
;
lex
->
result
=
0
;
lex
->
proc_list
.
first
=
0
;
lex
->
proc_list
.
first
=
0
;
lex
->
select_into_var_list
.
empty
();
}
}
...
...
sql/sql_yacc.yy
View file @
ed8b2529
...
@@ -632,7 +632,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
...
@@ -632,7 +632,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
handler_rkey_function handler_read_or_scan
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild union union_list
single_multi table_wild_list table_wild_one opt_wild union union_list
precision union_option opt_on_delete_item subselect_start opt_and
precision union_option opt_on_delete_item subselect_start opt_and
subselect_end select_var_list
subselect_end select_var_list
select_var_list_init
END_OF_INPUT
END_OF_INPUT
%type <NONE>
%type <NONE>
...
@@ -754,7 +754,8 @@ master_def:
...
@@ -754,7 +754,8 @@ master_def:
RELAY_LOG_POS_SYM EQ ULONG_NUM
RELAY_LOG_POS_SYM EQ ULONG_NUM
{
{
Lex->mi.relay_log_pos = $3;
Lex->mi.relay_log_pos = $3;
};
}
;
/* create a table */
/* create a table */
...
@@ -819,11 +820,13 @@ create:
...
@@ -819,11 +820,13 @@ create:
LEX *lex=Lex;
LEX *lex=Lex;
lex->udf.returns=(Item_result) $7;
lex->udf.returns=(Item_result) $7;
lex->udf.dl=$9.str;
lex->udf.dl=$9.str;
};
}
;
create2:
create2:
'(' field_list ')' opt_create_table_options create3 {}
'(' field_list ')' opt_create_table_options create3 {}
| opt_create_table_options create3 {};
| opt_create_table_options create3 {}
;
create3:
create3:
/* empty */ {}
/* empty */ {}
...
@@ -833,7 +836,8 @@ create3:
...
@@ -833,7 +836,8 @@ create3:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
mysql_init_select(lex);
}
}
select_options select_item_list opt_select_from union {};
select_options select_item_list opt_select_from union {}
;
opt_as:
opt_as:
/* empty */ {}
/* empty */ {}
...
@@ -2543,36 +2547,53 @@ procedure_item:
...
@@ -2543,36 +2547,53 @@ procedure_item:
YYABORT;
YYABORT;
if (!$2->name)
if (!$2->name)
$2->set_name($1,(uint) ((char*) Lex->tok_end - $1));
$2->set_name($1,(uint) ((char*) Lex->tok_end - $1));
};
}
;
select_var_list:
select_var_list ',' '@' ident_or_text
select_var_list_init:
{
{
if (Lex->select_into_var_list.push_back((LEX_STRING*) sql_memdup(&$4,sizeof(LEX_STRING)
)))
if (!(Lex->result= new select_dumpvar(
)))
YYABORT;
YYABORT;
}
}
| '@' ident_or_text
select_var_list
;
select_var_list:
select_var_list ',' select_var_ident
| select_var_ident {}
;
select_var_ident: '@' ident_or_text
{
{
if (Lex->select_into_var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
LEX *lex=Lex;
if ( ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
YYABORT;
YYABORT;
}
;
}
opt_into:
opt_into:
INTO OUTFILE TEXT_STRING
INTO OUTFILE TEXT_STRING
{
{
if (!(Lex->exchange= new sql_exchange($3.str,0)))
LEX *lex=Lex;
if (!(lex->exchange= new sql_exchange($3.str,0)))
YYABORT;
if (!(lex->result= new select_export(lex->exchange)))
YYABORT;
YYABORT;
}
}
opt_field_term opt_line_term
opt_field_term opt_line_term
| INTO DUMPFILE TEXT_STRING
| INTO DUMPFILE TEXT_STRING
{
{
if (!(Lex->exchange= new sql_exchange($3.str,1)))
LEX *lex=Lex;
if (!(lex->exchange= new sql_exchange($3.str,1)))
YYABORT;
if (!(lex->result= new select_dump(lex->exchange)))
YYABORT;
YYABORT;
}
}
| INTO select_var_list
| INTO select_var_list
_init
{
{
current_thd->safe_to_cache_query=0;
current_thd->safe_to_cache_query=0;
};
}
;
/*
/*
DO statement
DO statement
...
@@ -3582,7 +3603,8 @@ option_value:
...
@@ -3582,7 +3603,8 @@ option_value:
| PASSWORD FOR_SYM user equal text_or_password
| PASSWORD FOR_SYM user equal text_or_password
{
{
Lex->var_list.push_back(new set_var_password($3,$5));
Lex->var_list.push_back(new set_var_password($3,$5));
};
}
;
internal_variable_name:
internal_variable_name:
ident
ident
...
@@ -3591,7 +3613,8 @@ internal_variable_name:
...
@@ -3591,7 +3613,8 @@ internal_variable_name:
if (!tmp)
if (!tmp)
YYABORT;
YYABORT;
$$=tmp;
$$=tmp;
};
}
;
isolation_types:
isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
...
@@ -3612,7 +3635,8 @@ text_or_password:
...
@@ -3612,7 +3635,8 @@ text_or_password:
make_scrambled_password(buff,$3.str);
make_scrambled_password(buff,$3.str);
$$=buff;
$$=buff;
}
}
};
}
;
set_expr_or_default:
set_expr_or_default:
...
@@ -3642,16 +3666,19 @@ table_lock_list:
...
@@ -3642,16 +3666,19 @@ table_lock_list:
table_lock:
table_lock:
table_ident opt_table_alias lock_option
table_ident opt_table_alias lock_option
{ if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; };
{ if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }
;
lock_option:
lock_option:
READ_SYM { $$=TL_READ_NO_INSERT; }
READ_SYM { $$=TL_READ_NO_INSERT; }
| WRITE_SYM { $$=current_thd->update_lock_default; }
| WRITE_SYM { $$=current_thd->update_lock_default; }
| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
| READ_SYM LOCAL_SYM { $$= TL_READ; };
| READ_SYM LOCAL_SYM { $$= TL_READ; }
;
unlock:
unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; };
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
;
/*
/*
...
@@ -3681,15 +3708,18 @@ handler:
...
@@ -3681,15 +3708,18 @@ handler:
if (!add_table_to_list($2,0,0))
if (!add_table_to_list($2,0,0))
YYABORT;
YYABORT;
}
}
handler_read_or_scan where_clause limit_clause { };
handler_read_or_scan where_clause limit_clause { }
;
handler_read_or_scan:
handler_read_or_scan:
handler_scan_function { Lex->backup_dir= 0; }
handler_scan_function { Lex->backup_dir= 0; }
| ident handler_rkey_function { Lex->backup_dir= $1.str; };
| ident handler_rkey_function { Lex->backup_dir= $1.str; }
;
handler_scan_function:
handler_scan_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
| NEXT_SYM { Lex->ha_read_mode = RNEXT; };
| NEXT_SYM { Lex->ha_read_mode = RNEXT; }
;
handler_rkey_function:
handler_rkey_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
...
@@ -3703,14 +3733,16 @@ handler_rkey_function:
...
@@ -3703,14 +3733,16 @@ handler_rkey_function:
lex->ha_rkey_mode=$1;
lex->ha_rkey_mode=$1;
if (!(lex->insert_list = new List_item))
if (!(lex->insert_list = new List_item))
YYABORT;
YYABORT;
} '(' values ')' { };
} '(' values ')' { }
;
handler_rkey_mode:
handler_rkey_mode:
EQ { $$=HA_READ_KEY_EXACT; }
EQ { $$=HA_READ_KEY_EXACT; }
| GE { $$=HA_READ_KEY_OR_NEXT; }
| GE { $$=HA_READ_KEY_OR_NEXT; }
| LE { $$=HA_READ_KEY_OR_PREV; }
| LE { $$=HA_READ_KEY_OR_PREV; }
| GT_SYM { $$=HA_READ_AFTER_KEY; }
| GT_SYM { $$=HA_READ_AFTER_KEY; }
| LT { $$=HA_READ_BEFORE_KEY; };
| LT { $$=HA_READ_BEFORE_KEY; }
;
/* GRANT / REVOKE */
/* GRANT / REVOKE */
...
@@ -3748,7 +3780,8 @@ grant:
...
@@ -3748,7 +3780,8 @@ grant:
grant_privileges:
grant_privileges:
grant_privilege_list {}
grant_privilege_list {}
| ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
| ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
| ALL { Lex->grant = GLOBAL_ACLS;};
| ALL { Lex->grant = GLOBAL_ACLS;}
;
grant_privilege_list:
grant_privilege_list:
grant_privilege
grant_privilege
...
@@ -3867,7 +3900,8 @@ opt_table:
...
@@ -3867,7 +3900,8 @@ opt_table:
YYABORT;
YYABORT;
if (lex->grant == GLOBAL_ACLS)
if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL;
lex->grant = TABLE_ACLS & ~GRANT_ACL;
};
}
;
user_list:
user_list:
...
@@ -3898,7 +3932,8 @@ grant_user:
...
@@ -3898,7 +3932,8 @@ grant_user:
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$=$1; $1->password=$5 ; }
{ $$=$1; $1->password=$5 ; }
| user
| user
{ $$=$1; $1->password.str=NullS; };
{ $$=$1; $1->password.str=NullS; }
;
opt_column_list:
opt_column_list:
...
@@ -3931,7 +3966,8 @@ column_list_id:
...
@@ -3931,7 +3966,8 @@ column_list_id:
point->rights |= lex->which_columns;
point->rights |= lex->which_columns;
else
else
lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
};
}
;
require_clause: /* empty */
require_clause: /* empty */
...
@@ -3950,7 +3986,8 @@ require_clause: /* empty */
...
@@ -3950,7 +3986,8 @@ require_clause: /* empty */
| REQUIRE_SYM NONE_SYM
| REQUIRE_SYM NONE_SYM
{
{
Lex->ssl_type=SSL_TYPE_NONE;
Lex->ssl_type=SSL_TYPE_NONE;
};
}
;
grant_options:
grant_options:
/* empty */ {}
/* empty */ {}
...
@@ -3958,7 +3995,8 @@ grant_options:
...
@@ -3958,7 +3995,8 @@ grant_options:
grant_option_list:
grant_option_list:
grant_option_list grant_option {}
grant_option_list grant_option {}
| grant_option {};
| grant_option {}
;
grant_option:
grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;}
GRANT OPTION { Lex->grant |= GRANT_ACL;}
...
@@ -3976,14 +4014,16 @@ grant_option:
...
@@ -3976,14 +4014,16 @@ grant_option:
{
{
Lex->mqh.connections=$2;
Lex->mqh.connections=$2;
Lex->mqh.bits |= 4;
Lex->mqh.bits |= 4;
};
}
;
begin:
begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
opt_work:
opt_work:
/* empty */ {}
/* empty */ {}
| WORK_SYM {;};
| WORK_SYM {;}
;
commit:
commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
...
...
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