How can I generate the code-containing comments like mysqldump?
I'm needing to duplicate the mysqldump command in Python, and I am trying to figure out how automatically generate the code comments like mysqldump generates.
If you're wondering why I am doing such a stupid thing, it's because I am creating a utility that will make daily dumps of the production server for use in dev environments, but I must anonymize all of the fields that contain private data during the dump. It will also change API keys to test accounts, change passwords for important user accounts, etc. (Obviously this is not our main backup system, but something tailored for use by the devs, so that they can always use a safe snapshot of the production database to work with.)
I'm able to do a lot of this already, but I can't figure out how to automatically generate the correct "code comments" (e.g., "/*!40101 SET @saved_cs_client = @@character_set_client */;") that mysqldump includes before/after the CREATE TABLE statement and the INSERT statements. Obviously I could hard code them, but that just feels wrong, and is potentially short-sighted in terms of portability of code and longevity of use.
Thanks for any ideas you can share!
mysql mysqldump
bumped to the homepage by Community♦ 1 hour ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I'm needing to duplicate the mysqldump command in Python, and I am trying to figure out how automatically generate the code comments like mysqldump generates.
If you're wondering why I am doing such a stupid thing, it's because I am creating a utility that will make daily dumps of the production server for use in dev environments, but I must anonymize all of the fields that contain private data during the dump. It will also change API keys to test accounts, change passwords for important user accounts, etc. (Obviously this is not our main backup system, but something tailored for use by the devs, so that they can always use a safe snapshot of the production database to work with.)
I'm able to do a lot of this already, but I can't figure out how to automatically generate the correct "code comments" (e.g., "/*!40101 SET @saved_cs_client = @@character_set_client */;") that mysqldump includes before/after the CREATE TABLE statement and the INSERT statements. Obviously I could hard code them, but that just feels wrong, and is potentially short-sighted in terms of portability of code and longevity of use.
Thanks for any ideas you can share!
mysql mysqldump
bumped to the homepage by Community♦ 1 hour ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24
add a comment |
I'm needing to duplicate the mysqldump command in Python, and I am trying to figure out how automatically generate the code comments like mysqldump generates.
If you're wondering why I am doing such a stupid thing, it's because I am creating a utility that will make daily dumps of the production server for use in dev environments, but I must anonymize all of the fields that contain private data during the dump. It will also change API keys to test accounts, change passwords for important user accounts, etc. (Obviously this is not our main backup system, but something tailored for use by the devs, so that they can always use a safe snapshot of the production database to work with.)
I'm able to do a lot of this already, but I can't figure out how to automatically generate the correct "code comments" (e.g., "/*!40101 SET @saved_cs_client = @@character_set_client */;") that mysqldump includes before/after the CREATE TABLE statement and the INSERT statements. Obviously I could hard code them, but that just feels wrong, and is potentially short-sighted in terms of portability of code and longevity of use.
Thanks for any ideas you can share!
mysql mysqldump
I'm needing to duplicate the mysqldump command in Python, and I am trying to figure out how automatically generate the code comments like mysqldump generates.
If you're wondering why I am doing such a stupid thing, it's because I am creating a utility that will make daily dumps of the production server for use in dev environments, but I must anonymize all of the fields that contain private data during the dump. It will also change API keys to test accounts, change passwords for important user accounts, etc. (Obviously this is not our main backup system, but something tailored for use by the devs, so that they can always use a safe snapshot of the production database to work with.)
I'm able to do a lot of this already, but I can't figure out how to automatically generate the correct "code comments" (e.g., "/*!40101 SET @saved_cs_client = @@character_set_client */;") that mysqldump includes before/after the CREATE TABLE statement and the INSERT statements. Obviously I could hard code them, but that just feels wrong, and is potentially short-sighted in terms of portability of code and longevity of use.
Thanks for any ideas you can share!
mysql mysqldump
mysql mysqldump
asked Nov 17 '15 at 7:44
coreyp_1coreyp_1
1262
1262
bumped to the homepage by Community♦ 1 hour ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 1 hour ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24
add a comment |
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24
add a comment |
2 Answers
2
active
oldest
votes
Well you can review what mysqldump does on git and try working on it!! Though I'd not go this way...
Few things to suggest:
- You want to hide column names
--> use --no-create-info to dump only data. (onlydata.sql)
--> Have standard table definitions ready and intact for dev server. (definition.sql)
--> Refreshing dev => load definition.sql and then onlydata.sql
- Just to note that you can also restrict datadump with --where clauses and even limit that to dump only a few rows.
mysqldump --no-create-info --where " true limit 10000" | gzip > dump.sql.gz
.
- You want to remove few values from the dump? Well writing tool for searching strings will again cause long time to parse!
--> You might consider setting up a special slave on which you make your changes and then do a full datadump.
--> You can prepare SQL commands to run after dump load finishes as follows:
update secrettable set secretcolumn='xxxxxx' where secretcolumn='reallysecretthing';
add a comment |
First, I assume you understand the basic functionality of "code-containing comments."
/*!40101 some_sql_statement */
This means "only execute some_sql_statement
if you are a MySQL Server, version 4.01.01 or higher." So, there's no real need to wrap the statements in the comment syntax unless the dump files you are creating are going to handle backwards-compatibility with older versions of MySQL (or you want your backups to look exactly like mysqldump files, which isn't a bad idea). This is why the numbers vary -- the version indicates, for each statement, the version of MySQL server that would understand the statement. This is an attempt to make the files generated by mysqldump
to remain as backwards-compatible as possible.
But, onto the substance of your question.
Consider the statement you used as an example:
/*!40101 SET @saved_cs_client = @@character_set_client */;
This is a bad example, because it actually is static statement you can and should hard-code. From the source code to mysqldump, it's pretty low tech:
fprintf(sql_file,
"/*!50003 SET @saved_cs_client = @@character_set_client */ %sn"
"/*!50003 SET @saved_cs_results = @@character_set_results */ %sn"
"/*!50003 SET @saved_col_connection = @@collation_connection */ %sn"
...
The %s
above is just the statement delimiter (";
").
This is all in switch_cs_variables()
inside client/mysqldump.c
in the source files.
The next three lines from the same code use information that mysqldump learned from queries it sent to the server:
"/*!50003 SET character_set_client = %s */ %sn"
"/*!50003 SET character_set_results = %s */ %sn"
"/*!50003 SET collation_connection = %s */ %sn",
Looking at the source, the values used here are from character_set_client
, character_set_client
(again, it's used twice), and collation_connection
from the results of of SHOW CREATE [ trigger | function | procedure |event ]
.
Indeed, in thinking about this question, I remembered that I once wrote a similar script that generates a partial dump file, using perl. After collecting the data, I write them like this:
print "SET character_set_client = $def->{character_set_client};n";
print "SET character_set_results = $def->{character_set_client};n";
print "SET collation_connection = $def->{collation_connection};n";
Note that I didn't bother with the version-specific comment wrapper since I don't have any need to replay these files on any system that is old enough not to recognize these statements.
Note, also, that the static statements -- that is, the SET @saved...
statements ... as well as (later in the dump, not shown above) SET @@... = @saved...
statements, are simply there to set the session back to its prior state after each object is created.
Don't forget that when you're selecting data from the server, MySQL has its own built-in QUOTE()
function which will do more correct quoting of string literals (the data you're selecting, for insert) than anything you roll yourself.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f121306%2fhow-can-i-generate-the-code-containing-comments-like-mysqldump%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Well you can review what mysqldump does on git and try working on it!! Though I'd not go this way...
Few things to suggest:
- You want to hide column names
--> use --no-create-info to dump only data. (onlydata.sql)
--> Have standard table definitions ready and intact for dev server. (definition.sql)
--> Refreshing dev => load definition.sql and then onlydata.sql
- Just to note that you can also restrict datadump with --where clauses and even limit that to dump only a few rows.
mysqldump --no-create-info --where " true limit 10000" | gzip > dump.sql.gz
.
- You want to remove few values from the dump? Well writing tool for searching strings will again cause long time to parse!
--> You might consider setting up a special slave on which you make your changes and then do a full datadump.
--> You can prepare SQL commands to run after dump load finishes as follows:
update secrettable set secretcolumn='xxxxxx' where secretcolumn='reallysecretthing';
add a comment |
Well you can review what mysqldump does on git and try working on it!! Though I'd not go this way...
Few things to suggest:
- You want to hide column names
--> use --no-create-info to dump only data. (onlydata.sql)
--> Have standard table definitions ready and intact for dev server. (definition.sql)
--> Refreshing dev => load definition.sql and then onlydata.sql
- Just to note that you can also restrict datadump with --where clauses and even limit that to dump only a few rows.
mysqldump --no-create-info --where " true limit 10000" | gzip > dump.sql.gz
.
- You want to remove few values from the dump? Well writing tool for searching strings will again cause long time to parse!
--> You might consider setting up a special slave on which you make your changes and then do a full datadump.
--> You can prepare SQL commands to run after dump load finishes as follows:
update secrettable set secretcolumn='xxxxxx' where secretcolumn='reallysecretthing';
add a comment |
Well you can review what mysqldump does on git and try working on it!! Though I'd not go this way...
Few things to suggest:
- You want to hide column names
--> use --no-create-info to dump only data. (onlydata.sql)
--> Have standard table definitions ready and intact for dev server. (definition.sql)
--> Refreshing dev => load definition.sql and then onlydata.sql
- Just to note that you can also restrict datadump with --where clauses and even limit that to dump only a few rows.
mysqldump --no-create-info --where " true limit 10000" | gzip > dump.sql.gz
.
- You want to remove few values from the dump? Well writing tool for searching strings will again cause long time to parse!
--> You might consider setting up a special slave on which you make your changes and then do a full datadump.
--> You can prepare SQL commands to run after dump load finishes as follows:
update secrettable set secretcolumn='xxxxxx' where secretcolumn='reallysecretthing';
Well you can review what mysqldump does on git and try working on it!! Though I'd not go this way...
Few things to suggest:
- You want to hide column names
--> use --no-create-info to dump only data. (onlydata.sql)
--> Have standard table definitions ready and intact for dev server. (definition.sql)
--> Refreshing dev => load definition.sql and then onlydata.sql
- Just to note that you can also restrict datadump with --where clauses and even limit that to dump only a few rows.
mysqldump --no-create-info --where " true limit 10000" | gzip > dump.sql.gz
.
- You want to remove few values from the dump? Well writing tool for searching strings will again cause long time to parse!
--> You might consider setting up a special slave on which you make your changes and then do a full datadump.
--> You can prepare SQL commands to run after dump load finishes as follows:
update secrettable set secretcolumn='xxxxxx' where secretcolumn='reallysecretthing';
answered Nov 17 '15 at 8:05
mysql_usermysql_user
1,56468
1,56468
add a comment |
add a comment |
First, I assume you understand the basic functionality of "code-containing comments."
/*!40101 some_sql_statement */
This means "only execute some_sql_statement
if you are a MySQL Server, version 4.01.01 or higher." So, there's no real need to wrap the statements in the comment syntax unless the dump files you are creating are going to handle backwards-compatibility with older versions of MySQL (or you want your backups to look exactly like mysqldump files, which isn't a bad idea). This is why the numbers vary -- the version indicates, for each statement, the version of MySQL server that would understand the statement. This is an attempt to make the files generated by mysqldump
to remain as backwards-compatible as possible.
But, onto the substance of your question.
Consider the statement you used as an example:
/*!40101 SET @saved_cs_client = @@character_set_client */;
This is a bad example, because it actually is static statement you can and should hard-code. From the source code to mysqldump, it's pretty low tech:
fprintf(sql_file,
"/*!50003 SET @saved_cs_client = @@character_set_client */ %sn"
"/*!50003 SET @saved_cs_results = @@character_set_results */ %sn"
"/*!50003 SET @saved_col_connection = @@collation_connection */ %sn"
...
The %s
above is just the statement delimiter (";
").
This is all in switch_cs_variables()
inside client/mysqldump.c
in the source files.
The next three lines from the same code use information that mysqldump learned from queries it sent to the server:
"/*!50003 SET character_set_client = %s */ %sn"
"/*!50003 SET character_set_results = %s */ %sn"
"/*!50003 SET collation_connection = %s */ %sn",
Looking at the source, the values used here are from character_set_client
, character_set_client
(again, it's used twice), and collation_connection
from the results of of SHOW CREATE [ trigger | function | procedure |event ]
.
Indeed, in thinking about this question, I remembered that I once wrote a similar script that generates a partial dump file, using perl. After collecting the data, I write them like this:
print "SET character_set_client = $def->{character_set_client};n";
print "SET character_set_results = $def->{character_set_client};n";
print "SET collation_connection = $def->{collation_connection};n";
Note that I didn't bother with the version-specific comment wrapper since I don't have any need to replay these files on any system that is old enough not to recognize these statements.
Note, also, that the static statements -- that is, the SET @saved...
statements ... as well as (later in the dump, not shown above) SET @@... = @saved...
statements, are simply there to set the session back to its prior state after each object is created.
Don't forget that when you're selecting data from the server, MySQL has its own built-in QUOTE()
function which will do more correct quoting of string literals (the data you're selecting, for insert) than anything you roll yourself.
add a comment |
First, I assume you understand the basic functionality of "code-containing comments."
/*!40101 some_sql_statement */
This means "only execute some_sql_statement
if you are a MySQL Server, version 4.01.01 or higher." So, there's no real need to wrap the statements in the comment syntax unless the dump files you are creating are going to handle backwards-compatibility with older versions of MySQL (or you want your backups to look exactly like mysqldump files, which isn't a bad idea). This is why the numbers vary -- the version indicates, for each statement, the version of MySQL server that would understand the statement. This is an attempt to make the files generated by mysqldump
to remain as backwards-compatible as possible.
But, onto the substance of your question.
Consider the statement you used as an example:
/*!40101 SET @saved_cs_client = @@character_set_client */;
This is a bad example, because it actually is static statement you can and should hard-code. From the source code to mysqldump, it's pretty low tech:
fprintf(sql_file,
"/*!50003 SET @saved_cs_client = @@character_set_client */ %sn"
"/*!50003 SET @saved_cs_results = @@character_set_results */ %sn"
"/*!50003 SET @saved_col_connection = @@collation_connection */ %sn"
...
The %s
above is just the statement delimiter (";
").
This is all in switch_cs_variables()
inside client/mysqldump.c
in the source files.
The next three lines from the same code use information that mysqldump learned from queries it sent to the server:
"/*!50003 SET character_set_client = %s */ %sn"
"/*!50003 SET character_set_results = %s */ %sn"
"/*!50003 SET collation_connection = %s */ %sn",
Looking at the source, the values used here are from character_set_client
, character_set_client
(again, it's used twice), and collation_connection
from the results of of SHOW CREATE [ trigger | function | procedure |event ]
.
Indeed, in thinking about this question, I remembered that I once wrote a similar script that generates a partial dump file, using perl. After collecting the data, I write them like this:
print "SET character_set_client = $def->{character_set_client};n";
print "SET character_set_results = $def->{character_set_client};n";
print "SET collation_connection = $def->{collation_connection};n";
Note that I didn't bother with the version-specific comment wrapper since I don't have any need to replay these files on any system that is old enough not to recognize these statements.
Note, also, that the static statements -- that is, the SET @saved...
statements ... as well as (later in the dump, not shown above) SET @@... = @saved...
statements, are simply there to set the session back to its prior state after each object is created.
Don't forget that when you're selecting data from the server, MySQL has its own built-in QUOTE()
function which will do more correct quoting of string literals (the data you're selecting, for insert) than anything you roll yourself.
add a comment |
First, I assume you understand the basic functionality of "code-containing comments."
/*!40101 some_sql_statement */
This means "only execute some_sql_statement
if you are a MySQL Server, version 4.01.01 or higher." So, there's no real need to wrap the statements in the comment syntax unless the dump files you are creating are going to handle backwards-compatibility with older versions of MySQL (or you want your backups to look exactly like mysqldump files, which isn't a bad idea). This is why the numbers vary -- the version indicates, for each statement, the version of MySQL server that would understand the statement. This is an attempt to make the files generated by mysqldump
to remain as backwards-compatible as possible.
But, onto the substance of your question.
Consider the statement you used as an example:
/*!40101 SET @saved_cs_client = @@character_set_client */;
This is a bad example, because it actually is static statement you can and should hard-code. From the source code to mysqldump, it's pretty low tech:
fprintf(sql_file,
"/*!50003 SET @saved_cs_client = @@character_set_client */ %sn"
"/*!50003 SET @saved_cs_results = @@character_set_results */ %sn"
"/*!50003 SET @saved_col_connection = @@collation_connection */ %sn"
...
The %s
above is just the statement delimiter (";
").
This is all in switch_cs_variables()
inside client/mysqldump.c
in the source files.
The next three lines from the same code use information that mysqldump learned from queries it sent to the server:
"/*!50003 SET character_set_client = %s */ %sn"
"/*!50003 SET character_set_results = %s */ %sn"
"/*!50003 SET collation_connection = %s */ %sn",
Looking at the source, the values used here are from character_set_client
, character_set_client
(again, it's used twice), and collation_connection
from the results of of SHOW CREATE [ trigger | function | procedure |event ]
.
Indeed, in thinking about this question, I remembered that I once wrote a similar script that generates a partial dump file, using perl. After collecting the data, I write them like this:
print "SET character_set_client = $def->{character_set_client};n";
print "SET character_set_results = $def->{character_set_client};n";
print "SET collation_connection = $def->{collation_connection};n";
Note that I didn't bother with the version-specific comment wrapper since I don't have any need to replay these files on any system that is old enough not to recognize these statements.
Note, also, that the static statements -- that is, the SET @saved...
statements ... as well as (later in the dump, not shown above) SET @@... = @saved...
statements, are simply there to set the session back to its prior state after each object is created.
Don't forget that when you're selecting data from the server, MySQL has its own built-in QUOTE()
function which will do more correct quoting of string literals (the data you're selecting, for insert) than anything you roll yourself.
First, I assume you understand the basic functionality of "code-containing comments."
/*!40101 some_sql_statement */
This means "only execute some_sql_statement
if you are a MySQL Server, version 4.01.01 or higher." So, there's no real need to wrap the statements in the comment syntax unless the dump files you are creating are going to handle backwards-compatibility with older versions of MySQL (or you want your backups to look exactly like mysqldump files, which isn't a bad idea). This is why the numbers vary -- the version indicates, for each statement, the version of MySQL server that would understand the statement. This is an attempt to make the files generated by mysqldump
to remain as backwards-compatible as possible.
But, onto the substance of your question.
Consider the statement you used as an example:
/*!40101 SET @saved_cs_client = @@character_set_client */;
This is a bad example, because it actually is static statement you can and should hard-code. From the source code to mysqldump, it's pretty low tech:
fprintf(sql_file,
"/*!50003 SET @saved_cs_client = @@character_set_client */ %sn"
"/*!50003 SET @saved_cs_results = @@character_set_results */ %sn"
"/*!50003 SET @saved_col_connection = @@collation_connection */ %sn"
...
The %s
above is just the statement delimiter (";
").
This is all in switch_cs_variables()
inside client/mysqldump.c
in the source files.
The next three lines from the same code use information that mysqldump learned from queries it sent to the server:
"/*!50003 SET character_set_client = %s */ %sn"
"/*!50003 SET character_set_results = %s */ %sn"
"/*!50003 SET collation_connection = %s */ %sn",
Looking at the source, the values used here are from character_set_client
, character_set_client
(again, it's used twice), and collation_connection
from the results of of SHOW CREATE [ trigger | function | procedure |event ]
.
Indeed, in thinking about this question, I remembered that I once wrote a similar script that generates a partial dump file, using perl. After collecting the data, I write them like this:
print "SET character_set_client = $def->{character_set_client};n";
print "SET character_set_results = $def->{character_set_client};n";
print "SET collation_connection = $def->{collation_connection};n";
Note that I didn't bother with the version-specific comment wrapper since I don't have any need to replay these files on any system that is old enough not to recognize these statements.
Note, also, that the static statements -- that is, the SET @saved...
statements ... as well as (later in the dump, not shown above) SET @@... = @saved...
statements, are simply there to set the session back to its prior state after each object is created.
Don't forget that when you're selecting data from the server, MySQL has its own built-in QUOTE()
function which will do more correct quoting of string literals (the data you're selecting, for insert) than anything you roll yourself.
answered Nov 17 '15 at 23:50
Michael - sqlbotMichael - sqlbot
19.2k23261
19.2k23261
add a comment |
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f121306%2fhow-can-i-generate-the-code-containing-comments-like-mysqldump%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can't you tightly integrate C code with Python?
– Vérace
Nov 18 '15 at 0:24