sqlite2dbf 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/sqlite2dbf +25 -0
- data/lib/argparser.rb +113 -0
- data/lib/constants.rb +9 -0
- data/lib/file_checking.rb +89 -0
- data/lib/log.conf +53 -0
- data/lib/logging.rb +193 -0
- data/lib/sqlite2dbf.rb +136 -0
- data/lib/translating.rb +91 -0
- data/lib/translations +153 -0
- data/sqlite2dbf.gemspec +15 -0
- metadata +55 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 45babe3b6624235add48f6c62c22a5aaccefc294
|
4
|
+
data.tar.gz: bd7ed59177cb0fa945defa4e0413558bcdd5823b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c7920489b4c73e5f1799c8cf5a695ad97cd30dfe294b68cf377d9e02e53df306277223197b3fc5a1b8c77008e6dea5140163b87f71cc9c4438f323f58816ce99
|
7
|
+
data.tar.gz: 2dccbcbd83841acb53670181820f58f9cb1df999437f89d492894384a3a52a3dc5b64780097abddb0a4163100f6e1a612a3af7ad4247d8588d79036350397cc3
|
data/bin/sqlite2dbf
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2011-2013, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
require_relative '../lib/sqlite2dbf'
|
25
|
+
SQLite2DBF.new(*ARGV)
|
data/lib/argparser.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
|
23
|
+
|
24
|
+
require 'optparse'
|
25
|
+
require 'optparse/time'
|
26
|
+
require 'ostruct'
|
27
|
+
require_relative 'logging'
|
28
|
+
require_relative 'translating'
|
29
|
+
require_relative 'constants'
|
30
|
+
|
31
|
+
class ArgParser
|
32
|
+
include Logging
|
33
|
+
include Translating
|
34
|
+
|
35
|
+
self.extend(Logging)
|
36
|
+
self.extend(Translating)
|
37
|
+
@@log = init_logger()
|
38
|
+
|
39
|
+
# Returns a structure describing the options.
|
40
|
+
#
|
41
|
+
def self.parse(args)
|
42
|
+
# The options specified on the command line will be collected in <b>options</b>.
|
43
|
+
# We set default values here.
|
44
|
+
options = OpenStruct.new
|
45
|
+
options.debug = false
|
46
|
+
|
47
|
+
op = OptionParser.new do |opts|
|
48
|
+
opts.banner = "\n" << trl("Usage") << ":\t" << $APPNAME.dup << ' ' << trl("-s [sqlite-file] [options]") << "\n\t" << trl("or %s [Common options]") %($APPNAME)
|
49
|
+
|
50
|
+
opts.separator ""
|
51
|
+
opts.separator trl("Specific options") << ':'
|
52
|
+
opts.on('-' << trl("s"), '--' << trl("source/sqlite-file [FILE.sqlite]"), trl( "SQLite-file to read.")) do |source|
|
53
|
+
options.source = source
|
54
|
+
end
|
55
|
+
opts.on('-' << trl("t"), '--' << trl("dBase-files [FILE(0...n).dbf]"), trl( "Name for the dBase-files (1 per table) to be written.")) do |target|
|
56
|
+
options.target = target
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on('-' << trl('o'), trl("--orig"), trl('Use the table-name as file-name for the DBF-result')) do
|
60
|
+
options.table_name = true
|
61
|
+
end
|
62
|
+
|
63
|
+
=begin
|
64
|
+
|
65
|
+
# This is for later. The evaluation of the file-content may be allocated to the
|
66
|
+
# Configuration singleton, as it does not mean a lot of I/O nor does it imply
|
67
|
+
# much management.
|
68
|
+
|
69
|
+
opts.on("-c", "--config [CONFIG FILE]",
|
70
|
+
"Read alternative configuration from this file") do |conf|
|
71
|
+
$LOG.debug("config-file should be #{conf}") if $LOG
|
72
|
+
options.config = File.expand_path(conf )
|
73
|
+
end
|
74
|
+
opts.on("-g", "--generic [CONFIG FILE]",
|
75
|
+
"Write generic configuration options to this file") do |file|
|
76
|
+
options.generic = File.expand_path(file )
|
77
|
+
end
|
78
|
+
=end
|
79
|
+
opts.separator ""
|
80
|
+
opts.separator trl("Common options") << ':'
|
81
|
+
|
82
|
+
# No argument, shows at tail. This will print an options summary.
|
83
|
+
#
|
84
|
+
opts.on_tail(trl("-d"), trl("--debug"), trl("Show debug-messages") ) do
|
85
|
+
options.debug = true
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
opts.on_tail(trl("-h"), trl("--help"), trl("Show this message") ) do
|
90
|
+
puts opts
|
91
|
+
exit true
|
92
|
+
end
|
93
|
+
|
94
|
+
opts.on_tail(trl("-v"), trl("--version"), trl("Show version and program information") ) do
|
95
|
+
puts "\t#{$APPNAME}"
|
96
|
+
puts "\t© #{$YEARS}, } <#{$AUTHORS.join(', ')}>"
|
97
|
+
exit true
|
98
|
+
end
|
99
|
+
end
|
100
|
+
begin
|
101
|
+
op.parse!(args)
|
102
|
+
rescue OptionParser::ParseError => er
|
103
|
+
msg = trl("ERROR! Unsuitable or incomplete program-arguments") << (": %s" %er.message )
|
104
|
+
puts msg
|
105
|
+
puts trl("Start this program with parameter -h or --help to see the usage-message.")
|
106
|
+
exit false
|
107
|
+
end
|
108
|
+
|
109
|
+
options
|
110
|
+
end # parse()
|
111
|
+
|
112
|
+
end
|
113
|
+
|
data/lib/constants.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
|
23
|
+
=begin
|
24
|
+
A module to facilitate frequently occuring checks on
|
25
|
+
file-system objects. You can certainly do without this,
|
26
|
+
but maybe you find it useful.
|
27
|
+
=end
|
28
|
+
module File_Checking
|
29
|
+
|
30
|
+
@@text_messages = {
|
31
|
+
:exist? => "does not exist!",
|
32
|
+
:exist => "does not exist!",
|
33
|
+
:readable? => "is not readable!",
|
34
|
+
:readable => "is not readable!",
|
35
|
+
:executable? => "is not executable!",
|
36
|
+
:executable => "is not executable!",
|
37
|
+
:writable? => "is not writable!",
|
38
|
+
:writable => "is not writable!",
|
39
|
+
:directory? => "is not a directory!",
|
40
|
+
:directory => "is not a directory!",
|
41
|
+
:file? => "is not a file!",
|
42
|
+
:file => "is not a file!",
|
43
|
+
}
|
44
|
+
|
45
|
+
# Checks if the file with the name from the first
|
46
|
+
# parameter has the properties, listed in the second.
|
47
|
+
# The messages parameter is an array of one or several
|
48
|
+
# of :exist?, :readable?, :writable?, :directory? or
|
49
|
+
# their string-representations, respectively.
|
50
|
+
# Returns nil in case of success, otherwise an
|
51
|
+
# informative message, describing the first negative
|
52
|
+
# test-result.
|
53
|
+
def file_check(file, *messages)
|
54
|
+
File_Checking.file_check(file, *messages)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Checks if the file with the name from the first
|
58
|
+
# parameter has the properties, listed in the second.
|
59
|
+
# The messages parameter is an array of one or all
|
60
|
+
# of :exist?, :readable?, :writable?, :directory? or
|
61
|
+
# their string-representations, respectively.
|
62
|
+
# Returns nil in case of success, otherwise an
|
63
|
+
# informative message, describing the first negative
|
64
|
+
# test-result.
|
65
|
+
def self.file_check(file, *messages)
|
66
|
+
msg = nil
|
67
|
+
if(file && messages.respond_to?(:to_ary) && !messages.empty?)
|
68
|
+
messages.each do |k|
|
69
|
+
if(! k.to_s.end_with?('?'))
|
70
|
+
k = (k.to_s << '?').to_sym
|
71
|
+
end
|
72
|
+
@log.debug ('checking ' << k.to_s) if @log
|
73
|
+
if(msg == nil && File.respond_to?(k) && ! File.send(k, file.to_s))
|
74
|
+
msg = "#{file} #{@@text_messages[k.to_sym]}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
msg
|
79
|
+
end
|
80
|
+
alias :check_file :file_check
|
81
|
+
end
|
82
|
+
|
83
|
+
=begin
|
84
|
+
# example
|
85
|
+
|
86
|
+
include File_Checking
|
87
|
+
msg = file_check('some_file.txt', [:exist?, :readable?, 'writable'])
|
88
|
+
puts msg if msg
|
89
|
+
=end
|
data/lib/log.conf
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2013-2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
|
22
|
+
A simplified logger configuration. Set the level for each individual logger
|
23
|
+
below. Choose a different log-device or log-file if you like. Keep the
|
24
|
+
formatting intact. Do not change other sections of this file.
|
25
|
+
=end
|
26
|
+
|
27
|
+
# Do not touch from here ----->
|
28
|
+
require 'logger'
|
29
|
+
|
30
|
+
debug = Logger::DEBUG
|
31
|
+
info = Logger::INFO
|
32
|
+
error = Logger::ERROR
|
33
|
+
fatal = Logger::FATAL
|
34
|
+
warn = Logger::WARN
|
35
|
+
unknown = Logger::UNKNOWN
|
36
|
+
{
|
37
|
+
# <---------------- to here !
|
38
|
+
|
39
|
+
# Enter your settings here, but take into consideration that not all
|
40
|
+
# the named classes will really produce readable output. Well, you can
|
41
|
+
# always try... Either name just the log-level or make the log-level
|
42
|
+
# precede the output-device or output-file like in the examples.
|
43
|
+
|
44
|
+
# Example: naming a log-file
|
45
|
+
# :HtmlBuilder => [info, 'C:\temp\htmlbuilder.log']
|
46
|
+
# :HtmlBuilder => [debug, '/tmp/htmlbuilder.log'],
|
47
|
+
|
48
|
+
:SQLite2DBF => info,
|
49
|
+
|
50
|
+
# And ignore the remainder, too.
|
51
|
+
}
|
52
|
+
|
53
|
+
#eof
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
require 'logger'
|
23
|
+
require_relative 'file_checking'
|
24
|
+
|
25
|
+
=begin Creates a member @log and precede its output with the name of the class
|
26
|
+
of the object.
|
27
|
+
Example for a class-level logger:
|
28
|
+
# --------------------
|
29
|
+
class TClass
|
30
|
+
self.extend(Logging)
|
31
|
+
@@log = init_logger(STDOUT)
|
32
|
+
def test_log
|
33
|
+
@@log.info('class-level logger called from instance: ' << @@log.to_s)
|
34
|
+
@log = @@log
|
35
|
+
@log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
|
36
|
+
end
|
37
|
+
def self::test_log
|
38
|
+
@log.info('class-level logger called from class: ' << @log.to_s)
|
39
|
+
@@log.info('AGAIN: class-level logger called from class: ' << @@log.to_s)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
#---------------------
|
43
|
+
Example for a object-level logger:
|
44
|
+
ATTN! This means 1 logger per object.
|
45
|
+
# --------------------
|
46
|
+
class TClass
|
47
|
+
include Logging
|
48
|
+
def initialize
|
49
|
+
init_logger(STDOUT, Logger::DEBUG)
|
50
|
+
end
|
51
|
+
def test_log
|
52
|
+
@log.debug('called test_log() ')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
=end
|
56
|
+
module Logging
|
57
|
+
include File_Checking
|
58
|
+
|
59
|
+
@@have_log = false
|
60
|
+
@@LOG_CONF = File.dirname(File.absolute_path(__FILE__)) << File::Separator << 'log.conf'
|
61
|
+
|
62
|
+
# Call this method in an instance-method (e.g. initialize() ) to define the
|
63
|
+
# object-level logger; i.e. an object-specific member @log.
|
64
|
+
# Call this method within the class-definition for a class-level logger; i.e.
|
65
|
+
# a member @log for class-level acces.
|
66
|
+
# The method returns the logger, so you can actually do what you want with it.
|
67
|
+
def init_logger(target = STDOUT, level = Logger::INFO)
|
68
|
+
# Prepare for a class-level logger. This is actually quite cool.
|
69
|
+
|
70
|
+
# ---> Ingeniuous code starts here
|
71
|
+
cn = (self.class == Class ? name : self.class.name)
|
72
|
+
# <--- Ingeniuous code ends here
|
73
|
+
|
74
|
+
# allow to override the set log-levels with an
|
75
|
+
# external configuration (log.conf).
|
76
|
+
log_conf(cn)
|
77
|
+
# Or use the defaults as set here or elsewhere...
|
78
|
+
|
79
|
+
@level ||= level
|
80
|
+
@target ||= target
|
81
|
+
|
82
|
+
@log = Logger.new(@target)
|
83
|
+
@log.level = @level
|
84
|
+
|
85
|
+
@log.formatter = proc do |severity, datetime, progname, msg|
|
86
|
+
t = Time.now
|
87
|
+
"#{cn}: #{severity} #{t.hour}-#{t.min}-#{t.sec}: #{msg}\n"
|
88
|
+
end
|
89
|
+
if ! @@have_log
|
90
|
+
@log.debug cn.dup << ' reading logging-configuration from ' << @@LOG_CONF
|
91
|
+
@@have_log = true
|
92
|
+
@log.debug('level is ' << level.to_s)
|
93
|
+
end
|
94
|
+
return @log
|
95
|
+
end
|
96
|
+
|
97
|
+
# Set the log-target to an IO object.
|
98
|
+
def log_target=(target)
|
99
|
+
@target = target
|
100
|
+
@log = Logger.new(@@target)
|
101
|
+
@log.level = @level
|
102
|
+
end
|
103
|
+
|
104
|
+
# set the log-level
|
105
|
+
def log_level=(level)
|
106
|
+
@level = level
|
107
|
+
@log.level = @level
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Override or set the log-level and target-device, as set in a file 'log.conf'.
|
113
|
+
# I do not like the look of this, but it works just the way I want it to.
|
114
|
+
# "HEAVANS! Isn't there a standard way to do this in Ruby, for Christ's sake?", you say.
|
115
|
+
# Heck, I don't care. <= Read that again, I say.
|
116
|
+
def log_conf(cn = nil)
|
117
|
+
config = level = target = nil
|
118
|
+
# puts 'log-config is in ' << @@LOG_CONF
|
119
|
+
if(File::exist?(@@LOG_CONF) )
|
120
|
+
begin
|
121
|
+
conf = File.read(@@LOG_CONF)
|
122
|
+
config = instance_eval(conf)
|
123
|
+
rescue Exception => ex
|
124
|
+
STDERR.puts "WARNING! Cannot evaluate the logger-configuration!" << ' ' << ex.message
|
125
|
+
STDERR.puts "Default log-levels apply."
|
126
|
+
end
|
127
|
+
else
|
128
|
+
puts "Default log-levels apply."
|
129
|
+
end
|
130
|
+
|
131
|
+
if(config && config.respond_to?(:to_hash) )
|
132
|
+
config.default = nil
|
133
|
+
if cn
|
134
|
+
config = config[cn.to_sym]
|
135
|
+
else
|
136
|
+
config = config[self.class.name.to_sym]
|
137
|
+
end
|
138
|
+
|
139
|
+
if(config )
|
140
|
+
if(config.respond_to?(:to_ary) && config.size == 2)
|
141
|
+
@level, @target = config
|
142
|
+
@target.downcase!
|
143
|
+
logdir = File.dirname(@target)
|
144
|
+
msg = file_check(logdir, :exist?, :directory?, :writable?)
|
145
|
+
if(msg)
|
146
|
+
STDERR.puts "WARNING! A logfile for '%s' cannot be written to %s (%s)!" %[self.class.name, logdir, msg]
|
147
|
+
@target = nil
|
148
|
+
end
|
149
|
+
else
|
150
|
+
@level = config
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
######### test
|
158
|
+
if __FILE__ == $0
|
159
|
+
class TClass
|
160
|
+
# class level ---->
|
161
|
+
self.extend(Logging)
|
162
|
+
@@log = init_logger(STDOUT, Logger::INFO)
|
163
|
+
# <------
|
164
|
+
# object-level ---->
|
165
|
+
include Logging
|
166
|
+
# <---------
|
167
|
+
|
168
|
+
def test_log
|
169
|
+
@@log.info('class-level logger called from instance: ' << @@log.to_s)
|
170
|
+
#@log = @@log # works too
|
171
|
+
@log = TClass.class_eval{@log}
|
172
|
+
@log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
|
173
|
+
@log.debug("you won't see this on log-level INFO")
|
174
|
+
|
175
|
+
# object-level ---->
|
176
|
+
init_logger
|
177
|
+
# <-----------
|
178
|
+
@log.info("That's a different thing: " << @log.to_s << " - object-level logger!")
|
179
|
+
|
180
|
+
end
|
181
|
+
def self::test_log
|
182
|
+
@log.info('class-level logger called from class: ' << @log.to_s)
|
183
|
+
@@log.info('AGAIN: class-level logger called from class: ' << @log.to_s)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
TClass.new.test_log # class-logger + 1st object-logger
|
188
|
+
TClass.new.test_log # same class-logger + 2nd object-logger
|
189
|
+
|
190
|
+
TClass::test_log # same class-logger
|
191
|
+
puts 'And just say it once clearly: THIS IS COOOL!!'
|
192
|
+
end
|
193
|
+
#EOF
|
data/lib/sqlite2dbf.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
|
25
|
+
require_relative 'file_checking'
|
26
|
+
require_relative 'logging'
|
27
|
+
require 'shp'
|
28
|
+
require 'sqlite3'
|
29
|
+
require_relative 'argparser'
|
30
|
+
|
31
|
+
=begin
|
32
|
+
The main program class. Does it.
|
33
|
+
=end
|
34
|
+
|
35
|
+
class SQLite2DBF
|
36
|
+
include Logging
|
37
|
+
include Translating
|
38
|
+
|
39
|
+
def initialize(*args)
|
40
|
+
options = ArgParser::parse(args)
|
41
|
+
init_logger
|
42
|
+
level = (options.debug ? Logger::DEBUG : @log.level)
|
43
|
+
@log.level = level
|
44
|
+
@log.debug('options are: ' << options.to_s)
|
45
|
+
|
46
|
+
if(options.source)
|
47
|
+
sqlite_file = options.source
|
48
|
+
dbf_file = options.target if options.target
|
49
|
+
dbf_file = :table if options.table_name
|
50
|
+
dbf_file ||= File.dirname(sqlite_file) << File::Separator << File.basename(sqlite_file, '.*')
|
51
|
+
msg = nil
|
52
|
+
|
53
|
+
if(dbf_file != :table)
|
54
|
+
if(File.exist?(dbf_file))
|
55
|
+
msg = File_Checking.file_check(dbf_file, :file, :writable)
|
56
|
+
elsif(File.exist?(File.dirname(dbf_file)))
|
57
|
+
msg = File_Checking.file_check(File.dirname(dbf_file), :directory, :writable)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
msg ||= File_Checking.file_check(sqlite_file, :exist, :readable, :file)
|
62
|
+
|
63
|
+
if(!msg)
|
64
|
+
@log.debug('will transform ' << sqlite_file << ' to ' << dbf_file.to_s << '.dbf')
|
65
|
+
transform(sqlite_file, dbf_file)
|
66
|
+
else
|
67
|
+
msg = trl("ERROR! Unsuitable file") << " : %s" %msg
|
68
|
+
@log.error(msg)
|
69
|
+
exit false
|
70
|
+
end
|
71
|
+
else
|
72
|
+
puts trl("ERROR! Source-file is a mandatory program parameter!")
|
73
|
+
puts trl("Start this program with parameter -h or --help to see the usage-message.")
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def transform(sqlite_file, dbf_file)
|
81
|
+
# <------------ mapping SQLite-types to SHP/XBase ------------>
|
82
|
+
tmap = {'INT' => 1, 'TINYINT' => 1, 'SMALLINT' => 1, 'MEDIUMINT' => 1, 'BIGINT' => 1, 'UNSIGNED BIGINT' => 1, 'VARCHAR' => 0, 'CHARACTER' => 0, 'VARYING CHARACTER(255)' => 0, 'LONGVARCHAR' => 0, 'TEXT' => 0, 'INTEGER' => 1, 'FLOAT' => 2, 'REAL' => 2, 'DOUBLE' => 2}
|
83
|
+
# -----------> in a way ... <--------------
|
84
|
+
|
85
|
+
begin
|
86
|
+
SQLite3::Database.new(sqlite_file) do |db|
|
87
|
+
table_names = db.execute('select name from sqlite_master WHERE type="table"')
|
88
|
+
@log.debug('sqlite contains ' << table_names.size.to_s << ' table(s): ' << table_names.join(', '))
|
89
|
+
table_names.each_with_index do |tn, num|
|
90
|
+
tname = tn.join
|
91
|
+
table_info = db.table_info(tname)
|
92
|
+
@log.debug(tn[0] << ': ' << table_info.join)
|
93
|
+
content = db.execute('select * from ' << tname )
|
94
|
+
if(:table == dbf_file)
|
95
|
+
dbf_name = tname << (content.empty? ? '_empty' : '')<< '.dbf'
|
96
|
+
else
|
97
|
+
dbf_name = dbf_file.dup << num.to_s << (content.empty? ? '_empty' : '')<< '.dbf'
|
98
|
+
end
|
99
|
+
@log.debug('dbf will be ' << dbf_name)
|
100
|
+
dbt = SHP::DBF.create(dbf_name)
|
101
|
+
table_info.each_with_index do |field, index|
|
102
|
+
ftype = 0
|
103
|
+
# -----> determine the simple dbf data-type that has to do. <----
|
104
|
+
sql_type = tmap.keys.detect {|kt| field['type'].start_with?(kt) }
|
105
|
+
ftype ||= tmap[sql_type]
|
106
|
+
# <---- Yes. I know. ---->
|
107
|
+
|
108
|
+
dbt.add_field(field['name'], ftype, 200, 0)
|
109
|
+
end
|
110
|
+
|
111
|
+
content.each_with_index do |row, record_no|
|
112
|
+
@log.debug('row is ' << row.to_s)
|
113
|
+
row.each_with_index do |svalue, field_index|
|
114
|
+
type = table_info[field_index]['type']
|
115
|
+
@log.debug('field is ' << table_info[field_index]['name'] << ', svalue is ' << svalue.to_s << ', type is ' << type)
|
116
|
+
if(svalue)
|
117
|
+
dbt.write_string_attribute(record_no, field_index, svalue ) if 'TEXT' == type
|
118
|
+
begin
|
119
|
+
dbt.write_integer_attribute(record_no, field_index, svalue) if 'INTEGER' == type
|
120
|
+
dbt.write_double_attribute(record_no, field_index, svalue) if 'FLOAT' == type
|
121
|
+
rescue RangeError => ex
|
122
|
+
@log.error(trl("ERROR! cannot write value of type %s" %type) << ': ' << ex.message )
|
123
|
+
end
|
124
|
+
else
|
125
|
+
dbt.write_null_attribute(record_no, field_index) if (!svalue || type.empty?)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
dbt.close
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
rescue SQLite3::Exception => er
|
134
|
+
@log.error trl("ERROR! Cannot read the source-file") << ' (' << sqlite_file << "): %s" %er.message << '.'
|
135
|
+
end
|
136
|
+
end
|
data/lib/translating.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2015, Michael Uplawski *
|
5
|
+
* <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
|
25
|
+
RD = File.expand_path(File.dirname(__FILE__) ) + File::SEPARATOR if !defined?(RD)
|
26
|
+
|
27
|
+
require 'yaml'
|
28
|
+
require_relative 'file_checking'
|
29
|
+
|
30
|
+
|
31
|
+
=begin
|
32
|
+
A way to produce translated text in a ruby-program.
|
33
|
+
Translations are read from a file "translations" in the program folder.
|
34
|
+
=end
|
35
|
+
module Translating
|
36
|
+
# There are better ways to extend a translated
|
37
|
+
# string, but I keep the 'wild-card' for
|
38
|
+
# historical reasons.
|
39
|
+
@@awild = 'XX'
|
40
|
+
|
41
|
+
@@lang = nil
|
42
|
+
@@lang_file = format("%s%s", RD, 'LANG')
|
43
|
+
@@tr = YAML::load_file("#{RD}translations")
|
44
|
+
|
45
|
+
# find the current language-setting and return it.
|
46
|
+
def self.language()
|
47
|
+
if @@lang == nil
|
48
|
+
r = ENV['LANG']
|
49
|
+
if(r)
|
50
|
+
@@lang = r[0, 2]
|
51
|
+
elsif( !File_Checking::file_check(@@lang_file, [:exist?, :readable?]) && File::size(@@lang_file) >= 2)
|
52
|
+
File::open(@@lang_file, 'r') {|f| @@lang = f.readline}
|
53
|
+
@@lang.chomp!.downcase! if @@lang
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@@lang = 'en' if !@@lang
|
57
|
+
end
|
58
|
+
|
59
|
+
# Translate a string to the currently set langage.
|
60
|
+
# The args parameter may contain replacement-text which
|
61
|
+
# will appear at the positions indicated by wildcard-characters
|
62
|
+
# in the original string.
|
63
|
+
def self.trl(t, *args)
|
64
|
+
Translating::language()
|
65
|
+
lt = @@tr[t]
|
66
|
+
if(lt)
|
67
|
+
lt = lt[@@lang]
|
68
|
+
else
|
69
|
+
# File.open('/tmp/mtf', 'a+') {|f| f << t << "\n"}
|
70
|
+
puts "\nTRANSLATION MISSING: \"" << t << "\""
|
71
|
+
end
|
72
|
+
lt ||= t
|
73
|
+
if(args && !args.empty?)
|
74
|
+
i = -1
|
75
|
+
lt = lt.gsub(@@awild) do |a|
|
76
|
+
i += 1
|
77
|
+
args.flatten[i]
|
78
|
+
end
|
79
|
+
lt += args[i + 1, args.length].join
|
80
|
+
end
|
81
|
+
return lt
|
82
|
+
end
|
83
|
+
|
84
|
+
# Translate a string to the currently set langage.
|
85
|
+
# The args parameter may contain replacement-text which
|
86
|
+
# will appear at the positions indicated by wildcard-characters
|
87
|
+
# in the original string.
|
88
|
+
def trl(t, *args )
|
89
|
+
Translating::trl(t, args)
|
90
|
+
end
|
91
|
+
end
|
data/lib/translations
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
#
|
2
|
+
# ©2016-2016, Michael Uplawski <michael.uplawski@souris-libre.fr>
|
3
|
+
# This program is free software; you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation; either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program; if not, write to the
|
15
|
+
# Free Software Foundation, Inc.,
|
16
|
+
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
17
|
+
# =========================================================================
|
18
|
+
# These are the messages printed by SQLite2DBF. The first line of each
|
19
|
+
# block is the original english message, the following lines contain the
|
20
|
+
# translations for different locales.
|
21
|
+
|
22
|
+
# Keep this key 'SQLite2DB' as it is
|
23
|
+
|
24
|
+
SQLite2DBF:
|
25
|
+
|
26
|
+
Usage:
|
27
|
+
de: Aufrufsyntax
|
28
|
+
fr: Syntax
|
29
|
+
|
30
|
+
-s [sqlite-file] [options]:
|
31
|
+
de: -q [SQLite-Datei] [Optionen]
|
32
|
+
fr: -s [Fichier SQLite] [Options]
|
33
|
+
|
34
|
+
or %s [Common options]:
|
35
|
+
de: oder %s [Allgemeine Optionen]
|
36
|
+
fr: ou %s [Options généraux]
|
37
|
+
|
38
|
+
Specific options:
|
39
|
+
de: Spezielle Optionen
|
40
|
+
fr: Options spécifiques
|
41
|
+
|
42
|
+
# program argument -s (source)
|
43
|
+
s:
|
44
|
+
de: q
|
45
|
+
fr: s
|
46
|
+
|
47
|
+
source/sqlite-file [FILE.sqlite]:
|
48
|
+
de: quelle (SQLite) [Datei.sqlite]
|
49
|
+
fr: source (SQLite) [Fichier.sqlite]
|
50
|
+
|
51
|
+
SQLite-file to read.:
|
52
|
+
de: SQLite Datei, die gelesen wird.
|
53
|
+
fr: Fichier SQLite qui sera lu.
|
54
|
+
|
55
|
+
# program option -o (original table-name)
|
56
|
+
o:
|
57
|
+
de: t
|
58
|
+
fr: t
|
59
|
+
|
60
|
+
--orig:
|
61
|
+
de: --tab
|
62
|
+
fr: --tab
|
63
|
+
|
64
|
+
Table-names:
|
65
|
+
de: Namen der Tabellen
|
66
|
+
fr: Noms des tableaux
|
67
|
+
|
68
|
+
Use the table-name as file-name for the DBF-result:
|
69
|
+
de: Tabellen-Namen als Dateinamen für die DBF-Ausgabe verwenden
|
70
|
+
fr: Utiliser les noms des tableaux comme noms des fichiers DBF
|
71
|
+
|
72
|
+
ERROR! cannot write value of type INTEGER:
|
73
|
+
de: FEHLER! Kann INTEGER-Wert nicht schreiben
|
74
|
+
fr: ERREUR ! Ne peux pas écrire valeur de type 'INTEGER'
|
75
|
+
|
76
|
+
# program argument -t (target)
|
77
|
+
t:
|
78
|
+
de: z
|
79
|
+
fr: c
|
80
|
+
|
81
|
+
dBase-files [FILE(0...n).dbf]:
|
82
|
+
de: dBase Dateien [Datei(0...n).dbf]
|
83
|
+
fr: cible Fichier dBase [Fichier(0...n).dbf]
|
84
|
+
|
85
|
+
Name for the dBase-files (1 per table) to be written.:
|
86
|
+
de: Name der dBase-Dateien (1 pro Tabelle), die geschrieben werden.
|
87
|
+
fr: Nom des fichiers (1 par tableau) qui seront écris.
|
88
|
+
|
89
|
+
Common options:
|
90
|
+
de: Allgemeine Optionen
|
91
|
+
fr: Options généraux
|
92
|
+
|
93
|
+
# program argument -d (debug)
|
94
|
+
-d:
|
95
|
+
de: -d
|
96
|
+
fr: -d
|
97
|
+
|
98
|
+
--debug:
|
99
|
+
de: --debug
|
100
|
+
fr: --debug
|
101
|
+
|
102
|
+
Show debug-messages:
|
103
|
+
de: Debug Meldungen zeigen
|
104
|
+
fr: Afficher tous les messages
|
105
|
+
|
106
|
+
# program option -h (help)
|
107
|
+
-h:
|
108
|
+
de: -h
|
109
|
+
fr: -a
|
110
|
+
|
111
|
+
--help:
|
112
|
+
de: --hilfe
|
113
|
+
fr: --aide
|
114
|
+
|
115
|
+
Show this message:
|
116
|
+
de: Diese Nachricht anzeigen
|
117
|
+
fr: Afficher ce message
|
118
|
+
|
119
|
+
# program option -v (version)
|
120
|
+
-v:
|
121
|
+
de: -v
|
122
|
+
fr: -v
|
123
|
+
|
124
|
+
--version:
|
125
|
+
de: --version
|
126
|
+
fr: --version
|
127
|
+
|
128
|
+
Show version and program information:
|
129
|
+
de: Versions- und Programminformationen anzeigen
|
130
|
+
fr: Afficher des informations sur le logiciel et sa version
|
131
|
+
|
132
|
+
ERROR! Source-file is a mandatory program parameter!:
|
133
|
+
de: FEHLER! Quelldatei ist ein obligatorischer Programmparameter!
|
134
|
+
fr: ERREUR ! Source est un paramètre obligatoire !
|
135
|
+
|
136
|
+
Start this program with parameter -h or --help to see the usage-message.:
|
137
|
+
de: Wenn Sie das Programm mit dem Parameter -h oder mit --hilfe starten, wird die Eingabsyntax angezeigt.
|
138
|
+
fr: Lancez le logiciel avec le paramètre -a ou avec --aide, pour voir la syntax de l'entrée.
|
139
|
+
|
140
|
+
ERROR! Unsuitable or incomplete program-arguments:
|
141
|
+
de: FEHLER! Ungeeignete oder unvollständige Programmparameter
|
142
|
+
fr: ERREUR ! Paramètres invalides ou incomplètes
|
143
|
+
|
144
|
+
ERROR! Unsuitable file:
|
145
|
+
de: FEHLER! Ungeeignete Datei!
|
146
|
+
fr: ERREUR ! Fichier inapte !
|
147
|
+
|
148
|
+
ERROR! Cannot read the source-file:
|
149
|
+
de: FEHLER! Kann die Quelldatei nicht lesen
|
150
|
+
fr: ERREUR ! Source inlisible
|
151
|
+
|
152
|
+
|
153
|
+
# eof
|
data/sqlite2dbf.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'lib/constants'
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = $APPNAME
|
4
|
+
s.version = $VERSION
|
5
|
+
s.date = $DATE
|
6
|
+
s.summary = "missing files added."
|
7
|
+
s.description = "converts SQLite to DBase"
|
8
|
+
s.authors = $AUTHORS
|
9
|
+
s.email = $EMAIL
|
10
|
+
s.files = %w~sqlite2dbf~.collect{|f| 'bin/' << f} + %w~constants.rb argparser.rb sqlite2dbf.rb file_checking.rb log.conf logging.rb translating.rb translations ~.collect{|f| 'lib/' << f} + %w~sqlite2dbf.gemspec~.collect{|f|f}
|
11
|
+
s.requirements = 'shp, sqlite3'
|
12
|
+
s.executables = 'sqlite2dbf'
|
13
|
+
s.license = $LICENSE
|
14
|
+
s.required_ruby_version = '>= 2.3'
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sqlite2dbf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Uplawski <michael.uplawski@uplawski.eu>
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: converts SQLite to DBase
|
14
|
+
email: michael.uplawski@uplawski.eu
|
15
|
+
executables:
|
16
|
+
- sqlite2dbf
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/sqlite2dbf
|
21
|
+
- lib/argparser.rb
|
22
|
+
- lib/constants.rb
|
23
|
+
- lib/file_checking.rb
|
24
|
+
- lib/log.conf
|
25
|
+
- lib/logging.rb
|
26
|
+
- lib/sqlite2dbf.rb
|
27
|
+
- lib/translating.rb
|
28
|
+
- lib/translations
|
29
|
+
- sqlite2dbf.gemspec
|
30
|
+
homepage:
|
31
|
+
licenses:
|
32
|
+
- GPL-3.0
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.3'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements:
|
49
|
+
- shp, sqlite3
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 2.6.7
|
52
|
+
signing_key:
|
53
|
+
specification_version: 4
|
54
|
+
summary: missing files added.
|
55
|
+
test_files: []
|