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
ed8cc2a8
Commit
ed8cc2a8
authored
Dec 04, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
changing in Item_row according last review (SCRUM)
parent
91bd1e4c
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
105 additions
and
84 deletions
+105
-84
sql/item.h
sql/item.h
+1
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+39
-41
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+61
-2
sql/item_func.h
sql/item_func.h
+3
-41
sql/item_row.h
sql/item_row.h
+1
-0
No files found.
sql/item.h
View file @
ed8cc2a8
...
@@ -98,6 +98,7 @@ public:
...
@@ -98,6 +98,7 @@ public:
// Row emulation
// Row emulation
virtual
uint
cols
()
{
return
1
;
}
virtual
uint
cols
()
{
return
1
;
}
virtual
Item
*
el
(
uint
i
)
{
return
this
;
}
virtual
Item
*
el
(
uint
i
)
{
return
this
;
}
virtual
Item
**
addr
(
uint
i
)
{
return
0
;
}
virtual
bool
check_cols
(
uint
c
);
virtual
bool
check_cols
(
uint
c
);
};
};
...
...
sql/item_cmpfunc.cc
View file @
ed8cc2a8
...
@@ -106,7 +106,8 @@ void Item_bool_func2::fix_length_and_dec()
...
@@ -106,7 +106,8 @@ void Item_bool_func2::fix_length_and_dec()
{
{
if
(
convert_constant_item
(
field
,
&
args
[
1
]))
if
(
convert_constant_item
(
field
,
&
args
[
1
]))
{
{
arg_store
.
set_compare_func
(
this
,
INT_RESULT
);
// Works for all types.
cmp
.
set_cmp_func
(
this
,
tmp_arg
,
tmp_arg
+
1
,
INT_RESULT
);
// Works for all types.
return
;
return
;
}
}
}
}
...
@@ -118,7 +119,8 @@ void Item_bool_func2::fix_length_and_dec()
...
@@ -118,7 +119,8 @@ void Item_bool_func2::fix_length_and_dec()
{
{
if
(
convert_constant_item
(
field
,
&
args
[
0
]))
if
(
convert_constant_item
(
field
,
&
args
[
0
]))
{
{
arg_store
.
set_compare_func
(
this
,
INT_RESULT
);
// Works for all types.
cmp
.
set_cmp_func
(
this
,
tmp_arg
,
tmp_arg
+
1
,
INT_RESULT
);
// Works for all types.
return
;
return
;
}
}
}
}
...
@@ -133,8 +135,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
...
@@ -133,8 +135,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
1
:
0
];
1
:
0
];
if
(
type
==
ROW_RESULT
)
if
(
type
==
ROW_RESULT
)
{
{
uint
n
=
args
[
0
]
->
cols
();
uint
n
=
(
*
a
)
->
cols
();
if
(
n
!=
args
[
1
]
->
cols
())
if
(
n
!=
(
*
b
)
->
cols
())
{
{
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
n
);
my_error
(
ER_CARDINALITY_COL
,
MYF
(
0
),
n
);
comparators
=
0
;
comparators
=
0
;
...
@@ -142,11 +144,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
...
@@ -142,11 +144,7 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
}
}
if
((
comparators
=
(
Arg_comparator
*
)
sql_alloc
(
sizeof
(
Arg_comparator
)
*
n
)))
if
((
comparators
=
(
Arg_comparator
*
)
sql_alloc
(
sizeof
(
Arg_comparator
)
*
n
)))
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
comparators
[
i
].
set_cmp_func
(
owner
,
(
*
a
)
->
addr
(
i
),
(
*
b
)
->
addr
(
i
));
comparators
[
i
].
set_arg
(
0
,
args
[
0
]
->
el
(
i
));
comparators
[
i
].
set_arg
(
1
,
args
[
1
]
->
el
(
i
));
comparators
[
i
].
set_compare_func
(
owner
);
}
else
else
{
{
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
...
@@ -160,9 +158,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
...
@@ -160,9 +158,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
int
Arg_comparator
::
compare_string
()
int
Arg_comparator
::
compare_string
()
{
{
String
*
res1
,
*
res2
;
String
*
res1
,
*
res2
;
if
((
res1
=
args
[
0
]
->
val_str
(
&
owner
->
tmp_value1
)))
if
((
res1
=
(
*
a
)
->
val_str
(
&
owner
->
tmp_value1
)))
{
{
if
((
res2
=
args
[
1
]
->
val_str
(
&
owner
->
tmp_value2
)))
if
((
res2
=
(
*
b
)
->
val_str
(
&
owner
->
tmp_value2
)))
{
{
owner
->
null_value
=
0
;
owner
->
null_value
=
0
;
return
owner
->
binary
()
?
stringcmp
(
res1
,
res2
)
:
sortcmp
(
res1
,
res2
);
return
owner
->
binary
()
?
stringcmp
(
res1
,
res2
)
:
sortcmp
(
res1
,
res2
);
...
@@ -175,8 +173,8 @@ int Arg_comparator::compare_string()
...
@@ -175,8 +173,8 @@ int Arg_comparator::compare_string()
int
Arg_comparator
::
compare_e_string
()
int
Arg_comparator
::
compare_e_string
()
{
{
String
*
res1
,
*
res2
;
String
*
res1
,
*
res2
;
res1
=
args
[
0
]
->
val_str
(
&
owner
->
tmp_value1
);
res1
=
(
*
a
)
->
val_str
(
&
owner
->
tmp_value1
);
res2
=
args
[
1
]
->
val_str
(
&
owner
->
tmp_value2
);
res2
=
(
*
b
)
->
val_str
(
&
owner
->
tmp_value2
);
if
(
!
res1
||
!
res2
)
if
(
!
res1
||
!
res2
)
return
test
(
res1
==
res2
);
return
test
(
res1
==
res2
);
return
(
owner
->
binary
()
?
test
(
stringcmp
(
res1
,
res2
)
==
0
)
:
return
(
owner
->
binary
()
?
test
(
stringcmp
(
res1
,
res2
)
==
0
)
:
...
@@ -186,11 +184,11 @@ int Arg_comparator::compare_e_string()
...
@@ -186,11 +184,11 @@ int Arg_comparator::compare_e_string()
int
Arg_comparator
::
compare_real
()
int
Arg_comparator
::
compare_real
()
{
{
double
val1
=
args
[
0
]
->
val
();
double
val1
=
(
*
a
)
->
val
();
if
(
!
args
[
0
]
->
null_value
)
if
(
!
(
*
a
)
->
null_value
)
{
{
double
val2
=
args
[
1
]
->
val
();
double
val2
=
(
*
b
)
->
val
();
if
(
!
args
[
1
]
->
null_value
)
if
(
!
(
*
b
)
->
null_value
)
{
{
owner
->
null_value
=
0
;
owner
->
null_value
=
0
;
if
(
val1
<
val2
)
return
-
1
;
if
(
val1
<
val2
)
return
-
1
;
...
@@ -204,20 +202,20 @@ int Arg_comparator::compare_real()
...
@@ -204,20 +202,20 @@ int Arg_comparator::compare_real()
int
Arg_comparator
::
compare_e_real
()
int
Arg_comparator
::
compare_e_real
()
{
{
double
val1
=
args
[
0
]
->
val
();
double
val1
=
(
*
a
)
->
val
();
double
val2
=
args
[
1
]
->
val
();
double
val2
=
(
*
b
)
->
val
();
if
(
args
[
0
]
->
null_value
||
args
[
1
]
->
null_value
)
if
(
(
*
a
)
->
null_value
||
(
*
b
)
->
null_value
)
return
test
(
args
[
0
]
->
null_value
&&
args
[
1
]
->
null_value
);
return
test
(
(
*
a
)
->
null_value
&&
(
*
b
)
->
null_value
);
return
test
(
val1
==
val2
);
return
test
(
val1
==
val2
);
}
}
int
Arg_comparator
::
compare_int
()
int
Arg_comparator
::
compare_int
()
{
{
longlong
val1
=
args
[
0
]
->
val_int
();
longlong
val1
=
(
*
a
)
->
val_int
();
if
(
!
args
[
0
]
->
null_value
)
if
(
!
(
*
a
)
->
null_value
)
{
{
longlong
val2
=
args
[
1
]
->
val_int
();
longlong
val2
=
(
*
b
)
->
val_int
();
if
(
!
args
[
1
]
->
null_value
)
if
(
!
(
*
b
)
->
null_value
)
{
{
owner
->
null_value
=
0
;
owner
->
null_value
=
0
;
if
(
val1
<
val2
)
return
-
1
;
if
(
val1
<
val2
)
return
-
1
;
...
@@ -231,10 +229,10 @@ int Arg_comparator::compare_int()
...
@@ -231,10 +229,10 @@ int Arg_comparator::compare_int()
int
Arg_comparator
::
compare_e_int
()
int
Arg_comparator
::
compare_e_int
()
{
{
longlong
val1
=
args
[
0
]
->
val_int
();
longlong
val1
=
(
*
a
)
->
val_int
();
longlong
val2
=
args
[
1
]
->
val_int
();
longlong
val2
=
(
*
b
)
->
val_int
();
if
(
args
[
0
]
->
null_value
||
args
[
1
]
->
null_value
)
if
(
(
*
a
)
->
null_value
||
(
*
b
)
->
null_value
)
return
test
(
args
[
0
]
->
null_value
&&
args
[
1
]
->
null_value
);
return
test
(
(
*
a
)
->
null_value
&&
(
*
b
)
->
null_value
);
return
test
(
val1
==
val2
);
return
test
(
val1
==
val2
);
}
}
...
@@ -242,7 +240,7 @@ int Arg_comparator::compare_e_int()
...
@@ -242,7 +240,7 @@ int Arg_comparator::compare_e_int()
int
Arg_comparator
::
compare_row
()
int
Arg_comparator
::
compare_row
()
{
{
int
res
=
0
;
int
res
=
0
;
uint
n
=
args
[
0
]
->
cols
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
{
if
((
res
=
comparators
[
i
].
compare
()))
if
((
res
=
comparators
[
i
].
compare
()))
...
@@ -256,7 +254,7 @@ int Arg_comparator::compare_row()
...
@@ -256,7 +254,7 @@ int Arg_comparator::compare_row()
int
Arg_comparator
::
compare_e_row
()
int
Arg_comparator
::
compare_e_row
()
{
{
int
res
=
0
;
int
res
=
0
;
uint
n
=
args
[
0
]
->
cols
();
uint
n
=
(
*
a
)
->
cols
();
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
for
(
uint
i
=
0
;
i
<
n
;
i
++
)
{
{
if
((
res
=
comparators
[
i
].
compare
()))
if
((
res
=
comparators
[
i
].
compare
()))
...
@@ -268,7 +266,7 @@ int Arg_comparator::compare_e_row()
...
@@ -268,7 +266,7 @@ int Arg_comparator::compare_e_row()
longlong
Item_func_eq
::
val_int
()
longlong
Item_func_eq
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
==
0
?
1
:
0
;
return
value
==
0
?
1
:
0
;
}
}
...
@@ -283,39 +281,39 @@ void Item_func_equal::fix_length_and_dec()
...
@@ -283,39 +281,39 @@ void Item_func_equal::fix_length_and_dec()
longlong
Item_func_equal
::
val_int
()
longlong
Item_func_equal
::
val_int
()
{
{
return
arg_store
.
compare
();
return
cmp
.
compare
();
}
}
longlong
Item_func_ne
::
val_int
()
longlong
Item_func_ne
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
!=
0
&&
!
null_value
?
1
:
0
;
return
value
!=
0
&&
!
null_value
?
1
:
0
;
}
}
longlong
Item_func_ge
::
val_int
()
longlong
Item_func_ge
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
>=
0
?
1
:
0
;
return
value
>=
0
?
1
:
0
;
}
}
longlong
Item_func_gt
::
val_int
()
longlong
Item_func_gt
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
>
0
?
1
:
0
;
return
value
>
0
?
1
:
0
;
}
}
longlong
Item_func_le
::
val_int
()
longlong
Item_func_le
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
<=
0
&&
!
null_value
?
1
:
0
;
return
value
<=
0
&&
!
null_value
?
1
:
0
;
}
}
longlong
Item_func_lt
::
val_int
()
longlong
Item_func_lt
::
val_int
()
{
{
int
value
=
arg_store
.
compare
();
int
value
=
cmp
.
compare
();
return
value
<
0
&&
!
null_value
?
1
:
0
;
return
value
<
0
&&
!
null_value
?
1
:
0
;
}
}
...
@@ -664,7 +662,7 @@ double
...
@@ -664,7 +662,7 @@ double
Item_func_nullif
::
val
()
Item_func_nullif
::
val
()
{
{
double
value
;
double
value
;
if
(
!
arg_store
.
compare
()
||
null_value
)
if
(
!
cmp
.
compare
()
||
null_value
)
{
{
null_value
=
1
;
null_value
=
1
;
return
0.0
;
return
0.0
;
...
@@ -678,7 +676,7 @@ longlong
...
@@ -678,7 +676,7 @@ longlong
Item_func_nullif
::
val_int
()
Item_func_nullif
::
val_int
()
{
{
longlong
value
;
longlong
value
;
if
(
!
arg_store
.
compare
()
||
null_value
)
if
(
!
cmp
.
compare
()
||
null_value
)
{
{
null_value
=
1
;
null_value
=
1
;
return
0
;
return
0
;
...
@@ -692,7 +690,7 @@ String *
...
@@ -692,7 +690,7 @@ String *
Item_func_nullif
::
val_str
(
String
*
str
)
Item_func_nullif
::
val_str
(
String
*
str
)
{
{
String
*
res
;
String
*
res
;
if
(
!
arg_store
.
compare
()
||
null_value
)
if
(
!
cmp
.
compare
()
||
null_value
)
{
{
null_value
=
1
;
null_value
=
1
;
return
0
;
return
0
;
...
...
sql/item_cmpfunc.h
View file @
ed8cc2a8
...
@@ -21,6 +21,63 @@
...
@@ -21,6 +21,63 @@
#pragma interface
/* gcc class implementation */
#pragma interface
/* gcc class implementation */
#endif
#endif
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
class
Item_bool_func2
;
class
Arg_comparator
;
typedef
int
(
Arg_comparator
::*
arg_cmp_func
)();
class
Arg_comparator
:
public
Sql_alloc
{
Item
**
a
,
**
b
;
arg_cmp_func
func
;
Item_bool_func2
*
owner
;
Arg_comparator
*
comparators
;
// used only for compare_row()
public:
Arg_comparator
()
{};
Arg_comparator
(
Item
**
a1
,
Item
**
a2
)
:
a
(
a1
),
b
(
a2
)
{};
inline
void
seta
(
Item
**
item
)
{
a
=
item
;
}
inline
void
setb
(
Item
**
item
)
{
b
=
item
;
}
int
set_compare_func
(
Item_bool_func2
*
owner
,
Item_result
type
);
inline
int
set_compare_func
(
Item_bool_func2
*
owner
)
{
return
set_compare_func
(
owner
,
item_cmp_type
((
*
a
)
->
result_type
(),
(
*
b
)
->
result_type
()));
}
inline
int
set_cmp_func
(
Item_bool_func2
*
owner
,
Item
**
a1
,
Item
**
a2
,
Item_result
type
)
{
a
=
a1
;
b
=
a2
;
return
set_compare_func
(
owner
,
type
);
}
inline
int
set_cmp_func
(
Item_bool_func2
*
owner
,
Item
**
a1
,
Item
**
a2
)
{
return
set_cmp_func
(
owner
,
a1
,
a2
,
item_cmp_type
((
*
a1
)
->
result_type
(),
(
*
a2
)
->
result_type
()));
}
inline
int
compare
()
{
return
(
this
->*
func
)();
}
int
compare_string
();
// compare args[0] & args[1]
int
compare_real
();
// compare args[0] & args[1]
int
compare_int
();
// compare args[0] & args[1]
int
compare_row
();
// compare args[0] & args[1]
int
compare_e_string
();
// compare args[0] & args[1]
int
compare_e_real
();
// compare args[0] & args[1]
int
compare_e_int
();
// compare args[0] & args[1]
int
compare_e_row
();
// compare args[0] & args[1]
static
arg_cmp_func
comparator_matrix
[
4
][
2
];
friend
class
Item_func
;
};
class
Item_bool_func
:
public
Item_int_func
class
Item_bool_func
:
public
Item_int_func
{
{
public:
public:
...
@@ -33,13 +90,15 @@ public:
...
@@ -33,13 +90,15 @@ public:
class
Item_bool_func2
:
public
Item_int_func
class
Item_bool_func2
:
public
Item_int_func
{
/* Bool with 2 string args */
{
/* Bool with 2 string args */
protected:
protected:
Arg_comparator
cmp
;
String
tmp_value1
,
tmp_value2
;
String
tmp_value1
,
tmp_value2
;
public:
public:
Item_bool_func2
(
Item
*
a
,
Item
*
b
)
:
Item_int_func
(
a
,
b
)
{}
Item_bool_func2
(
Item
*
a
,
Item
*
b
)
:
Item_int_func
(
a
,
b
),
cmp
(
tmp_arg
,
tmp_arg
+
1
)
{}
void
fix_length_and_dec
();
void
fix_length_and_dec
();
void
set_cmp_func
()
void
set_cmp_func
()
{
{
arg_store
.
set_compare_func
(
this
);
cmp
.
set_cmp_func
(
this
,
tmp_arg
,
tmp_arg
+
1
);
}
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_OP
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_OP
;
}
virtual
enum
Functype
rev_functype
()
const
{
return
UNKNOWN_FUNC
;
}
virtual
enum
Functype
rev_functype
()
const
{
return
UNKNOWN_FUNC
;
}
...
...
sql/item_func.h
View file @
ed8cc2a8
...
@@ -28,48 +28,10 @@ extern "C" /* Bug in BSDI include file */
...
@@ -28,48 +28,10 @@ extern "C" /* Bug in BSDI include file */
}
}
#endif
#endif
extern
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
);
class
Item_bool_func2
;
class
Arg_comparator
;
typedef
int
(
Arg_comparator
::*
arg_cmp_func
)();
class
Arg_comparator
:
public
Sql_alloc
{
Item
*
args
[
2
];
arg_cmp_func
func
;
Item_bool_func2
*
owner
;
Arg_comparator
*
comparators
;
// used only for compare_row()
public:
inline
void
set_arg
(
int
i
,
Item
*
item
)
{
args
[
i
]
=
item
;
}
int
set_compare_func
(
Item_bool_func2
*
owner
,
Item_result
type
);
inline
int
set_compare_func
(
Item_bool_func2
*
owner
)
{
return
set_compare_func
(
owner
,
item_cmp_type
(
args
[
0
]
->
result_type
(),
args
[
1
]
->
result_type
()));
}
inline
int
compare
()
{
return
(
this
->*
func
)();
}
int
compare_string
();
// compare args[0] & args[1]
int
compare_real
();
// compare args[0] & args[1]
int
compare_int
();
// compare args[0] & args[1]
int
compare_row
();
// compare args[0] & args[1]
int
compare_e_string
();
// compare args[0] & args[1]
int
compare_e_real
();
// compare args[0] & args[1]
int
compare_e_int
();
// compare args[0] & args[1]
int
compare_e_row
();
// compare args[0] & args[1]
static
arg_cmp_func
comparator_matrix
[
4
][
2
];
friend
class
Item_func
;
};
class
Item_func
:
public
Item_result_field
class
Item_func
:
public
Item_result_field
{
{
protected:
protected:
Item
**
args
;
Item
**
args
,
*
tmp_arg
[
2
];
Arg_comparator
arg_store
;
uint
allowed_arg_cols
;
uint
allowed_arg_cols
;
public:
public:
uint
arg_count
;
uint
arg_count
;
...
@@ -96,14 +58,14 @@ public:
...
@@ -96,14 +58,14 @@ public:
Item_func
(
Item
*
a
)
:
Item_func
(
Item
*
a
)
:
allowed_arg_cols
(
1
),
arg_count
(
1
)
allowed_arg_cols
(
1
),
arg_count
(
1
)
{
{
args
=
arg_store
.
args
;
args
=
tmp_arg
;
args
[
0
]
=
a
;
args
[
0
]
=
a
;
with_sum_func
=
a
->
with_sum_func
;
with_sum_func
=
a
->
with_sum_func
;
}
}
Item_func
(
Item
*
a
,
Item
*
b
)
:
Item_func
(
Item
*
a
,
Item
*
b
)
:
allowed_arg_cols
(
1
),
arg_count
(
2
)
allowed_arg_cols
(
1
),
arg_count
(
2
)
{
{
args
=
arg_store
.
args
;
args
=
tmp_arg
;
args
[
0
]
=
a
;
args
[
1
]
=
b
;
args
[
0
]
=
a
;
args
[
1
]
=
b
;
with_sum_func
=
a
->
with_sum_func
||
b
->
with_sum_func
;
with_sum_func
=
a
->
with_sum_func
||
b
->
with_sum_func
;
}
}
...
...
sql/item_row.h
View file @
ed8cc2a8
...
@@ -61,5 +61,6 @@ public:
...
@@ -61,5 +61,6 @@ public:
virtual
uint
cols
()
{
return
arg_count
;
}
virtual
uint
cols
()
{
return
arg_count
;
}
virtual
Item
*
el
(
uint
i
)
{
return
items
[
i
];
}
virtual
Item
*
el
(
uint
i
)
{
return
items
[
i
];
}
virtual
Item
**
addr
(
uint
i
)
{
return
items
+
i
;
}
virtual
bool
check_cols
(
uint
c
);
virtual
bool
check_cols
(
uint
c
);
};
};
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