Skip to content

Instantly share code, notes, and snippets.

@davidlj95
Last active August 29, 2015 14:14
Show Gist options
  • Save davidlj95/b78947bc3074e206c659 to your computer and use it in GitHub Desktop.
Save davidlj95/b78947bc3074e206c659 to your computer and use it in GitHub Desktop.
MySQL2SQLite3.sh
#=============================================================================#
# __ __ _____ ____ _ ___ _____ ____ _ _ _ #
# | \/ | / ____|/ __ \| | |__ \ / ____|/ __ \| | (_) | #
# | \ / |_ _| (___ | | | | | ) | | (___ | | | | | _| |_ ___ #
# | |\/| | | | |\___ \| | | | | / / \___ \| | | | | | | __/ _ \ #
# | | | | |_| |____) | |__| | |____ / /_ ____) | |__| | |____| | || __/ #
# |_| |_|\__, |_____/ \___\_\______| |____| |_____/ \___\_\______|_|\__\___| #
# __/ | #
# |___/ #
# #
#-----------------------------------------------------------------------------#
# USAGE #
#-----------------------------------------------------------------------------#
# See below HELP function or use -h option to see some usage help #
# #
#-----------------------------------------------------------------------------#
# CREDITS #
#-----------------------------------------------------------------------------#
# #
#.................................. AUTHORS ..................................#
# @davidlj95 mySQL2SQLite3.sh #
# https://gist.github.com/davidlj95/b78947bc3074e206c659 #
# #
#.................................. BASED ON .................................#
# @esperlu mysql2sqlite.sh #
# https://gist.github.com/esperlu/943776 #
# #
#=============================================================================#
#=============================================================================#
# START BASH #
#=============================================================================#
#!/bin/bash
#=============================================================================#
# GLOBAL VARIABLES #
#=============================================================================#
## OPTIONS ##
declare -a g_Options=(0)
#=============================================================================#
# HELP #
# #
# Shows a help message to show users how to use the script #
#=============================================================================#
function help {
## TITLE ##
echo -e \
"==========================================================================\n"\
" MYSQL TO SQLITE SCRIPT \n"\
"==========================================================================\n"\
"\n"\
" DESCRIPTION:\n"\
"--------------------------------------------------------------------------\n"\
" Given a database name, user and password, converts the MySQL dump of\n"\
" that database into a SQLite3 compatible file\n"\
" The difference between the base version made by @esperlu in GitHub is\n"\
" that takes care about encoding to use accents (using UTF8 encoding)\n\n"\
" USAGE:\n"\
"--------------------------------------------------------------------------\n"\
" The syntax to use the script is the following\n\n"\
" $0 -u \"DB_Username\" -p \"DB_Pass\" -d \"DB_Name\" file [-e] [-h]\n\n"\
"\t OPTIONS:\n"\
"\t\t -u Username\n"\
"\t\t Username to setup a connection with the database\n"\
"\t\t -p Password\n"\
"\t\t Password of the previous username\n"\
"\t\t -d Database\n"\
"\t\t Database to convert\n"\
"\t\t -e \"Extra arguments\"\n"\
"\t\t Extra arguments to pass to mysqldump\n"\
"\t\t -h\n"\
"\t\t Show help and exit\n"\
" EXAMPLE:\n"\
"--------------------------------------------------------------------------\n"\
" Convert exampleDB with user/pass admin/admin into file myDB.sqlite\n"\
" $0 -u \"admin\" -p \"admin\" -d \"exampleDB\" myDB.sqlite\n\n"\
" AUTHORS:\n"\
"--------------------------------------------------------------------------\n"\
" @davidlj95 based on @esperlu from GitHub"
}
#=============================================================================#
# PARSE OPTIONS #
# #
# Given the options of the script, tries to get all options and its values #
# and saves them into the global options variables #
# #
# If missing mandatory options, exits #
# #
# @param array - array of options ($@) #
#=============================================================================#
function parseOptions {
#-------------------------------------------------------------------------#
# Variables #
#-------------------------------------------------------------------------#
local user=""
local pass=""
local database=""
local file=""
local extra=""
#-------------------------------------------------------------------------#
# Parse options #
#-------------------------------------------------------------------------#
while getopts :u:p:d:e:h option
do
case $option in
# HELP
h) help && exit;;
# USER
u) user=$OPTARG;;
# PASS
p) pass=$OPTARG;;
# DATABASE
d) database=$OPTARG;;
# EXTRA
e) extra=$OPTARG;;
# NON-IDENTIFIED
*)
>&2 echo "(Error) One or more options do not exist ($OPTIND)"
>&2 echo " Use -h to see help"
exit;;
esac
done
#-------------------------------------------------------------------------#
# Parse arguments #
#-------------------------------------------------------------------------#
# Update pointer
shift $(($OPTIND -1))
#File
if [ "$1" == "" ]
then
>&2 echo "(Error) No output file specified"
>&2 echo " Use -h to see help using the script"
exit
else
file="$1"
fi
#-------------------------------------------------------------------------#
# Save options #
#-------------------------------------------------------------------------#
g_Options[0]=$user
g_Options[1]=$pass
g_Options[2]=$database
g_Options[3]=$file
g_Options[4]=$extra
}
#=============================================================================#
# GETTERS #
# #
# Helpers to get from the global options variable in an easy way #
# They echo the queried option #
#=============================================================================#
function getOption { echo "${g_Options[$1]}" ; }
function getUser { getOption 0 ; }
function getPass { getOption 1 ; }
function getDatabase { getOption 2 ; }
function getOutputFile { getOption 3 ; }
function getExtra { getOption 4 ; }
function getTemp { echo ".mysql2sqlite.tmp" ; }
#=============================================================================#
# GENERATE MYSQLDUMP #
# #
# Generates a dump from the MySQL database to then convert it to SQLite #
#=============================================================================#
function generate_mysqldump {
#-------------------------------------------------------------------------#
# Variables #
#-------------------------------------------------------------------------#
local opt_User=$(getUser)
local opt_Pass=$(getPass)
local opt_DB=$(getDatabase)
local opt_File=$(getOutputFile)
local opt_Extra=$(getExtra)
#-------------------------------------------------------------------------#
# Options #
#-------------------------------------------------------------------------#
## USER ##
if ! [ "$opt_User" == "" ]
then
opt_User="--user=$opt_User"
fi
## PASS ##
if ! [ "$opt_Pass" == "" ]
then
opt_Pass="--password=$opt_Pass"
fi
## FILE ##
opt_File="--result-file=$opt_File"
#-------------------------------------------------------------------------#
# MySQLDump #
#-------------------------------------------------------------------------#
mysqldump --compatible=ansi --skip-extended-insert --compact\
$opt_File $opt_User $opt_Pass $opt_DB $opt_Extra
}
#=============================================================================#
# MYSQL2SQLITE #
# #
# Converts a MySQL dump to SQLite compatible database file #
# They echo the queried option #
#=============================================================================#
function mysql2sqlite {
#-------------------------------------------------------------------------#
# Variables #
#-------------------------------------------------------------------------#
(awk '
BEGIN {
FS=",$"
print "PRAGMA synchronous = OFF;"
print "PRAGMA journal_mode = MEMORY;"
print "BEGIN TRANSACTION;"
}
# CREATE TRIGGER statements have funny commenting
# Remember we are in trigger.
/^\/\*.*CREATE.*TRIGGER/ {
gsub( /^.*TRIGGER/, "CREATE TRIGGER" )
print
inTrigger = 1
next
}
# The end of CREATE TRIGGER has a stray comment terminator
/END \*\/;;/ { gsub( /\*\//, "" ); print; inTrigger = 0; next }
# The rest of triggers just get passed through
inTrigger != 0 { print; next }
# Skip other comments
/^\/\*/ { next }
# Print all `INSERT` lines
# The single quotes are protected by another single quote.
/INSERT/ {
gsub( /\\\047/, "\047\047" )
gsub(/\\n/, "\n")
gsub(/\\r/, "\r")
gsub(/\\"/, "\"")
gsub(/\\\\/, "\\")
gsub(/\\\032/, "\032")
print
next
}
# Print the `CREATE` line as is and capture the table name.
/^CREATE/ {
print
if (match($0,/\"[^\"]+/)) tableName = substr($0,RSTART+1,RLENGTH-1)
}
# Replace `FULLTEXT KEY` or any other `XXXXX KEY` except PRIMARY by `KEY`
/^ [^"]+KEY/ && !/^ PRIMARY KEY/ { gsub( /.+KEY/, " KEY" ) }
# Get rid of field lengths in KEY lines
/ KEY/ { gsub(/\([0-9]+\)/, "") }
# Print all fields definition lines except the `KEY` lines.
/^ / && !/^( KEY|\);)/ {
gsub( /AUTO_INCREMENT|auto_increment/, "" )
gsub( /(CHARACTER SET|character set) [^ ]+ /, "" )
gsub( /DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP|default current_timestamp on update current_timestamp/, "" )
gsub( /(COLLATE|collate) [^ ]+ /, "" )
gsub(/(ENUM|enum)[^)]+\)/, "text ")
gsub(/(SET|set)\([^)]+\)/, "text ")
gsub(/UNSIGNED|unsigned/, "")
if (prev) print prev ","
prev = $1
}
# `KEY` lines are extracted from the `CREATE` block and stored in
# array for later print
# in a separate `CREATE KEY` command. The index name is prefixed by the
# table name to avoid a sqlite error for duplicate index name.
/^( KEY|\);)/ {
if (prev) print prev
prev=""
if ($0 == ");"){
print
} else {
if ( match( $0, /\"[^"]+/ ) ) indexName = substr( $0, RSTART+1, RLENGTH-1 )
if ( match( $0, /\([^()]+/ ) ) indexKey = substr( $0, RSTART+1, RLENGTH-1 )
key[tableName]=key[tableName] "CREATE INDEX \"" tableName "_" indexName "\" ON \"" tableName "\" (" indexKey ");\n"
}
}
# Print all `KEY` creation lines.
END {
for (table in key) printf key[table]
print "END TRANSACTION;"
}
' < $(getOutputFile)) > $(getTemp)
#-------------------------------------------------------------------------#
# Generate SQLite3 #
#-------------------------------------------------------------------------#
# Remove MySQL dump
rm $(getOutputFile)
# Generate database
cat $(getTemp) | sqlite3 $(getOutputFile)
# Remove temp file
rm $(getTemp)
}
#=============================================================================#
# COMMANDS #
#=============================================================================#
# 0. PARSE OPTIONS
parseOptions $@
# 1. GENERATE MYSQLDUMP
generate_mysqldump
# 2. CONVERT
mysql2sqlite
@davidlj95
Copy link
Author

mySQL2SQLite3 Script

The aim of this shell script is to convert a MySQL database into a SQLite3 file containing a copy of that database, taking care of the encoding UTF8

The script is based on @esperlu mysql2sqlite.sh script and just improves the way to use it, a little bit of help and takes care about encoding. The main script is the same.

Usage

The usage is a little bit different of @esperlu original script, but not so much.

Make it executable

First of all, make the script executable:

  1. Download the script and open a terminal
  2. Change to the current directory
  3. Make it executable:
    chmod +x mySQL2SQLite3.sh
  4. Run it (see below for arguments details)

Arguments

The following arguments are available:

  • -u username: username to connect to MySQL local server
  • -p password: password of the previous option user
  • -d database: database to convert
  • [-e extras]: extra arguments to pass to mysqldump (such as --no-data to just get the database structure and not all records, for more arguments type in your terminal man mysqldump)
  • [-h]: Shows help to use the script
  • file: File to save SQLite3 file to (will overwrite it if exists)

Example

Convert exampleDB with user/pass admin/admin into file myDB.sqlite, with just structure
./mySQL2SQLite3.sh -u "admin" -p "admin" -d "exampleDB" -e "--no-data" myDB.sqlite

Credits

The script is based in @esperlu mysql2sqlite.sh shell script. All the AWK code is from there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment