- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Java developer new to Scala
Wed, 2012-02-08, 20:39
Hi people.
My background is in java development so I thought scala should not be that hard to learn.
I think there isn't a better way to learn an new language than to have an actual problem to solve. So the issue I've looked into is to build a simple text parser to change data from MySQL dump file to a format that sqlite would consider correct for init of an database.
My goal of this mail isn't to ask for an solution. I just wanted to get some hints or tips on which concepts to look future into to improve my code. At the moment I've implemented code that could gather all the create statements and create the tables in sqlite.
I'll add my code and an example of an dump from mysql so you'll see what kind of data that could occur during this processing. The code is quite adhoc at the moment so I know I could do alot of simplifications. But because I don't know the language that well and don't have any scala developers closeby so I can't get hints, tips, tricks or pointers to improve either.
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
import scala.io._
import scala.collection.mutable.ArrayBuffer
class Statement {
var name = ""
var sqltype = ""
var notNullable = false
var default = ""
var autoincrement = false
var sqlStr = ""
var havePrimeKey = false
override def toString :String = {
if(sqlStr != "")
return sqlStr
if(autoincrement && sqltype.indexOf("int") != -1)
sqltype = "integer primary key autoincrement"
var str = name+" "+sqltype
if(notNullable)
str += " NOT NULL"
if(default != "")
str += " DEFAULT "+default
return str
}
}
object ReadFile extends Application {
// val s = Source.fromFile("dump.sql", "UTF-8")
val s = Source.fromFile("dump2.sql", "UTF-8")
var createArr = new Array[String](3)
var createStatArr = new ArrayBuffer[Statement]
var createStatement = false
val out = new java.io.FileWriter("c:/temp/sqltest/createtables.sql")
var table = ""
var havePrime = false
s.getLines.foreach( (line) => {
if(line.trim.toLowerCase.startsWith("create")) {
createStatement = true
createArr = line.split("`")
if(createArr.length > 1) {
table = createArr.apply(1)
out.write("drop table if exists '"+table+"';\n")
out.write("create table '"+table+"' (\n")
}
}
if(createStatement && line.trim.startsWith(")")) {
createStatement = false
var first = true
var havePrimeKey = false
createStatArr.foreach( (stat) => {
if(!first)
out.write(",\n")
out.write("\t"+stat.toString())
first = false
})
out.write("\n);\n\n")
createStatArr = new ArrayBuffer[Statement]
havePrime = false
}
if(createStatement) {
if(!(line.trim.toLowerCase.startsWith("create") ||
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("unique key") ||
line.trim.toLowerCase.startsWith("key") ||
line.trim.toLowerCase.startsWith("constraint"))
) {
createArr = line.trim.split(' ')
var stat = new Statement
if(createArr.length > 1) {
stat.name = createArr.apply(0)
var linestr = createArr.apply(1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
stat.sqltype = linestr
if(createArr.apply(1).startsWith("enum"))
stat.sqltype = "varchar(9)"
if(line.indexOf("NOT NULL") != -1)
stat.notNullable = true
if(line.toLowerCase().indexOf("auto_increment") != -1) {
stat.autoincrement = true
havePrime = true
}
for(i <- 0 until createArr.length) {
if(createArr.apply(i).compareToIgnoreCase("default") == 0) {
var linestr = createArr.apply(i+1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
if(linestr.compareTo("CURRENT_TIMESTAMP") == 0)
linestr = "'0000-00-00 00:00:00'"
if(linestr.compareTo("'0000-00-00") == 0)
linestr = "'0000-00-00 00:00:00'"
stat.default = linestr
}
}
createStatArr += stat
}
}
if(
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("constraint")
) {
var stat = new Statement
var linestr = line.trim()
stat.sqlStr = line.trim
if(linestr.endsWith(",")) {
stat.sqlStr = linestr.substring(0, linestr.length()-1);
}
if(!havePrime || linestr.indexOf("PRIMARY") == -1)
createStatArr += stat
}
}
})
out.close
}
------------------------------------------------------------------------- END --------------------------------------------------------------------------
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
CREATE TABLE `table1` (
`oneId` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anotherId` int(11) unsigned NOT NULL,
`creationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`theblob` blob NOT NULL,
`hashKey` varchar(16) NOT NULL,
PRIMARY KEY (`oneId`),
UNIQUE KEY `hashKey` (`hashKey`)
) ENGINE=InnoDB AUTO_INCREMENT=240 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `table1`
--
LOCK TABLES `table1` WRITE;
/*!40000 ALTER TABLE `table1` DISABLE KEYS */;
INSERT INTO `table1` VALUES (1,2,'2010-08-06 11:52:54',0xfaff80988e80eee7798,'fafasd'),(2,142456,'2010-07-30 11:11:29',0xfaff80988e80eee7798,'asfaew'),(3,220748,'2010-08-03 06:16:24',0xfaff80988e80eee7798,'ar5hffgadbf');
/*!40000 ALTER TABLE `table1` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `table2`
--
DROP TABLE IF EXISTS `table2`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `table2` (
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`type` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL DEFAULT '0',
`data1` int(11) NOT NULL DEFAULT '0',
`blob1` blob,
`blob2` blob,
`bool` tinyint(1) NOT NULL DEFAULT '0',
KEY `table2Key1` (`type`),
KEY `table2Key2` (`id`),
KEY `table2Key3` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--------------------------------------------------------------------------END --------------------------------------------------------------------------
Best regards
Daniel
My background is in java development so I thought scala should not be that hard to learn.
I think there isn't a better way to learn an new language than to have an actual problem to solve. So the issue I've looked into is to build a simple text parser to change data from MySQL dump file to a format that sqlite would consider correct for init of an database.
My goal of this mail isn't to ask for an solution. I just wanted to get some hints or tips on which concepts to look future into to improve my code. At the moment I've implemented code that could gather all the create statements and create the tables in sqlite.
I'll add my code and an example of an dump from mysql so you'll see what kind of data that could occur during this processing. The code is quite adhoc at the moment so I know I could do alot of simplifications. But because I don't know the language that well and don't have any scala developers closeby so I can't get hints, tips, tricks or pointers to improve either.
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
import scala.io._
import scala.collection.mutable.ArrayBuffer
class Statement {
var name = ""
var sqltype = ""
var notNullable = false
var default = ""
var autoincrement = false
var sqlStr = ""
var havePrimeKey = false
override def toString :String = {
if(sqlStr != "")
return sqlStr
if(autoincrement && sqltype.indexOf("int") != -1)
sqltype = "integer primary key autoincrement"
var str = name+" "+sqltype
if(notNullable)
str += " NOT NULL"
if(default != "")
str += " DEFAULT "+default
return str
}
}
object ReadFile extends Application {
// val s = Source.fromFile("dump.sql", "UTF-8")
val s = Source.fromFile("dump2.sql", "UTF-8")
var createArr = new Array[String](3)
var createStatArr = new ArrayBuffer[Statement]
var createStatement = false
val out = new java.io.FileWriter("c:/temp/sqltest/createtables.sql")
var table = ""
var havePrime = false
s.getLines.foreach( (line) => {
if(line.trim.toLowerCase.startsWith("create")) {
createStatement = true
createArr = line.split("`")
if(createArr.length > 1) {
table = createArr.apply(1)
out.write("drop table if exists '"+table+"';\n")
out.write("create table '"+table+"' (\n")
}
}
if(createStatement && line.trim.startsWith(")")) {
createStatement = false
var first = true
var havePrimeKey = false
createStatArr.foreach( (stat) => {
if(!first)
out.write(",\n")
out.write("\t"+stat.toString())
first = false
})
out.write("\n);\n\n")
createStatArr = new ArrayBuffer[Statement]
havePrime = false
}
if(createStatement) {
if(!(line.trim.toLowerCase.startsWith("create") ||
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("unique key") ||
line.trim.toLowerCase.startsWith("key") ||
line.trim.toLowerCase.startsWith("constraint"))
) {
createArr = line.trim.split(' ')
var stat = new Statement
if(createArr.length > 1) {
stat.name = createArr.apply(0)
var linestr = createArr.apply(1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
stat.sqltype = linestr
if(createArr.apply(1).startsWith("enum"))
stat.sqltype = "varchar(9)"
if(line.indexOf("NOT NULL") != -1)
stat.notNullable = true
if(line.toLowerCase().indexOf("auto_increment") != -1) {
stat.autoincrement = true
havePrime = true
}
for(i <- 0 until createArr.length) {
if(createArr.apply(i).compareToIgnoreCase("default") == 0) {
var linestr = createArr.apply(i+1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
if(linestr.compareTo("CURRENT_TIMESTAMP") == 0)
linestr = "'0000-00-00 00:00:00'"
if(linestr.compareTo("'0000-00-00") == 0)
linestr = "'0000-00-00 00:00:00'"
stat.default = linestr
}
}
createStatArr += stat
}
}
if(
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("constraint")
) {
var stat = new Statement
var linestr = line.trim()
stat.sqlStr = line.trim
if(linestr.endsWith(",")) {
stat.sqlStr = linestr.substring(0, linestr.length()-1);
}
if(!havePrime || linestr.indexOf("PRIMARY") == -1)
createStatArr += stat
}
}
})
out.close
}
------------------------------------------------------------------------- END --------------------------------------------------------------------------
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
CREATE TABLE `table1` (
`oneId` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anotherId` int(11) unsigned NOT NULL,
`creationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`theblob` blob NOT NULL,
`hashKey` varchar(16) NOT NULL,
PRIMARY KEY (`oneId`),
UNIQUE KEY `hashKey` (`hashKey`)
) ENGINE=InnoDB AUTO_INCREMENT=240 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `table1`
--
LOCK TABLES `table1` WRITE;
/*!40000 ALTER TABLE `table1` DISABLE KEYS */;
INSERT INTO `table1` VALUES (1,2,'2010-08-06 11:52:54',0xfaff80988e80eee7798,'fafasd'),(2,142456,'2010-07-30 11:11:29',0xfaff80988e80eee7798,'asfaew'),(3,220748,'2010-08-03 06:16:24',0xfaff80988e80eee7798,'ar5hffgadbf');
/*!40000 ALTER TABLE `table1` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `table2`
--
DROP TABLE IF EXISTS `table2`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `table2` (
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`type` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL DEFAULT '0',
`data1` int(11) NOT NULL DEFAULT '0',
`blob1` blob,
`blob2` blob,
`bool` tinyint(1) NOT NULL DEFAULT '0',
KEY `table2Key1` (`type`),
KEY `table2Key2` (`id`),
KEY `table2Key3` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--------------------------------------------------------------------------END --------------------------------------------------------------------------
Best regards
Daniel
Wed, 2012-02-08, 21:51
#2
Re: Java developer new to Scala
I don't have too much time so my examples are the best, but might help you get to the next level of the language.
In the interest of learning and being more "scala"-like. Two things that really jump out at me are the use of var and return statements.
Var is the biggest no-no. Try to restructure the application by not using any variables. I try to only use vars within a method and then normally only in a performance critical tight loop. Also sometimes in tests for convenience when testing side effects like IO.
Second try to not use returns.
if(sqlStr == null) { val typeString = if(autoincrement && sqltype contains "int) "integer primary key autoincrement" else sqltype val nullString = if(notNullable) " NOT NULL" else "" val defaultString = if(default != "") " DEFAULT "+default else "" name + typeString + nullString + defaultString (if(notNullable) } else { sqlStr}
There are more but that is all I have time with.
Enjoy scala.
JesseOn Wed, Feb 8, 2012 at 8:39 PM, Daniel Persson <mailto.woden@gmail.com> wrote:
In the interest of learning and being more "scala"-like. Two things that really jump out at me are the use of var and return statements.
Var is the biggest no-no. Try to restructure the application by not using any variables. I try to only use vars within a method and then normally only in a performance critical tight loop. Also sometimes in tests for convenience when testing side effects like IO.
Second try to not use returns.
if(sqlStr == null) { val typeString = if(autoincrement && sqltype contains "int) "integer primary key autoincrement" else sqltype val nullString = if(notNullable) " NOT NULL" else "" val defaultString = if(default != "") " DEFAULT "+default else "" name + typeString + nullString + defaultString (if(notNullable) } else { sqlStr}
There are more but that is all I have time with.
Enjoy scala.
JesseOn Wed, Feb 8, 2012 at 8:39 PM, Daniel Persson <mailto.woden@gmail.com> wrote:
Hi people.
My background is in java development so I thought scala should not be that hard to learn.
I think there isn't a better way to learn an new language than to have an actual problem to solve. So the issue I've looked into is to build a simple text parser to change data from MySQL dump file to a format that sqlite would consider correct for init of an database.
My goal of this mail isn't to ask for an solution. I just wanted to get some hints or tips on which concepts to look future into to improve my code. At the moment I've implemented code that could gather all the create statements and create the tables in sqlite.
I'll add my code and an example of an dump from mysql so you'll see what kind of data that could occur during this processing. The code is quite adhoc at the moment so I know I could do alot of simplifications. But because I don't know the language that well and don't have any scala developers closeby so I can't get hints, tips, tricks or pointers to improve either.
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
import scala.io._
import scala.collection.mutable.ArrayBuffer
class Statement {
var name = ""
var sqltype = ""
var notNullable = false
var default = ""
var autoincrement = false
var sqlStr = ""
var havePrimeKey = false
override def toString :String = {
if(sqlStr != "")
return sqlStr
if(autoincrement && sqltype.indexOf("int") != -1)
sqltype = "integer primary key autoincrement"
var str = name+" "+sqltype
if(notNullable)
str += " NOT NULL"
if(default != "")
str += " DEFAULT "+default
return str
}
}
object ReadFile extends Application {
// val s = Source.fromFile("dump.sql", "UTF-8")
val s = Source.fromFile("dump2.sql", "UTF-8")
var createArr = new Array[String](3)
var createStatArr = new ArrayBuffer[Statement]
var createStatement = false
val out = new java.io.FileWriter("c:/temp/sqltest/createtables.sql")
var table = ""
var havePrime = false
s.getLines.foreach( (line) => {
if(line.trim.toLowerCase.startsWith("create")) {
createStatement = true
createArr = line.split("`")
if(createArr.length > 1) {
table = createArr.apply(1)
out.write("drop table if exists '"+table+"';\n")
out.write("create table '"+table+"' (\n")
}
}
if(createStatement && line.trim.startsWith(")")) {
createStatement = false
var first = true
var havePrimeKey = false
createStatArr.foreach( (stat) => {
if(!first)
out.write(",\n")
out.write("\t"+stat.toString())
first = false
})
out.write("\n);\n\n")
createStatArr = new ArrayBuffer[Statement]
havePrime = false
}
if(createStatement) {
if(!(line.trim.toLowerCase.startsWith("create") ||
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("unique key") ||
line.trim.toLowerCase.startsWith("key") ||
line.trim.toLowerCase.startsWith("constraint"))
) {
createArr = line.trim.split(' ')
var stat = new Statement
if(createArr.length > 1) {
stat.name = createArr.apply(0)
var linestr = createArr.apply(1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
stat.sqltype = linestr
if(createArr.apply(1).startsWith("enum"))
stat.sqltype = "varchar(9)"
if(line.indexOf("NOT NULL") != -1)
stat.notNullable = true
if(line.toLowerCase().indexOf("auto_increment") != -1) {
stat.autoincrement = true
havePrime = true
}
for(i <- 0 until createArr.length) {
if(createArr.apply(i).compareToIgnoreCase("default") == 0) {
var linestr = createArr.apply(i+1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
if(linestr.compareTo("CURRENT_TIMESTAMP") == 0)
linestr = "'0000-00-00 00:00:00'"
if(linestr.compareTo("'0000-00-00") == 0)
linestr = "'0000-00-00 00:00:00'"
stat.default = linestr
}
}
createStatArr += stat
}
}
if(
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("constraint")
) {
var stat = new Statement
var linestr = line.trim()
stat.sqlStr = line.trim
if(linestr.endsWith(",")) {
stat.sqlStr = linestr.substring(0, linestr.length()-1);
}
if(!havePrime || linestr.indexOf("PRIMARY") == -1)
createStatArr += stat
}
}
})
out.close
}
------------------------------------------------------------------------- END --------------------------------------------------------------------------
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
CREATE TABLE `table1` (
`oneId` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anotherId` int(11) unsigned NOT NULL,
`creationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`theblob` blob NOT NULL,
`hashKey` varchar(16) NOT NULL,
PRIMARY KEY (`oneId`),
UNIQUE KEY `hashKey` (`hashKey`)
) ENGINE=InnoDB AUTO_INCREMENT=240 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `table1`
--
LOCK TABLES `table1` WRITE;
/*!40000 ALTER TABLE `table1` DISABLE KEYS */;
INSERT INTO `table1` VALUES (1,2,'2010-08-06 11:52:54',0xfaff80988e80eee7798,'fafasd'),(2,142456,'2010-07-30 11:11:29',0xfaff80988e80eee7798,'asfaew'),(3,220748,'2010-08-03 06:16:24',0xfaff80988e80eee7798,'ar5hffgadbf');
/*!40000 ALTER TABLE `table1` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `table2`
--
DROP TABLE IF EXISTS `table2`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `table2` (
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`type` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL DEFAULT '0',
`data1` int(11) NOT NULL DEFAULT '0',
`blob1` blob,
`blob2` blob,
`bool` tinyint(1) NOT NULL DEFAULT '0',
KEY `table2Key1` (`type`),
KEY `table2Key2` (`id`),
KEY `table2Key3` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--------------------------------------------------------------------------END --------------------------------------------------------------------------
Best regards
Daniel
Wed, 2012-02-08, 23:51
#3
Re: Java developer new to Scala
You can use codereview.stackexchange.com to ask for advice like this.
There hasn't been much Scala traffic, but it seems people who do put
Scala stuff there are happy with the answers they get.
On Wed, Feb 8, 2012 at 17:39, Daniel Persson wrote:
> Hi people.
>
> My background is in java development so I thought scala should not be that
> hard to learn.
>
> I think there isn't a better way to learn an new language than to have an
> actual problem to solve. So the issue I've looked into is to build a simple
> text parser to change data from MySQL dump file to a format that sqlite
> would consider correct for init of an database.
>
> My goal of this mail isn't to ask for an solution. I just wanted to get some
> hints or tips on which concepts to look future into to improve my code. At
> the moment I've implemented code that could gather all the create statements
> and create the tables in sqlite.
>
> I'll add my code and an example of an dump from mysql so you'll see what
> kind of data that could occur during this processing. The code is quite
> adhoc at the moment so I know I could do alot of simplifications. But
> because I don't know the language that well and don't have any scala
> developers closeby so I can't get hints, tips, tricks or pointers to improve
> either.
>
> -------------------------------------------------------------------------
> CUT
> --------------------------------------------------------------------------
> import scala.io._
> import scala.collection.mutable.ArrayBuffer
>
> class Statement {
> var name = ""
> var sqltype = ""
> var notNullable = false
> var default = ""
> var autoincrement = false
> var sqlStr = ""
> var havePrimeKey = false
>
> override def toString :String = {
> if(sqlStr != "")
> return sqlStr
> if(autoincrement && sqltype.indexOf("int") != -1)
> sqltype = "integer primary key autoincrement"
>
> var str = name+" "+sqltype
> if(notNullable)
> str += " NOT NULL"
> if(default != "")
> str += " DEFAULT "+default
> return str
> }
> }
>
> object ReadFile extends Application {
> // val s = Source.fromFile("dump.sql", "UTF-8")
> val s = Source.fromFile("dump2.sql", "UTF-8")
> var createArr = new Array[String](3)
> var createStatArr = new ArrayBuffer[Statement]
> var createStatement = false
> val out = new java.io.FileWriter("c:/temp/sqltest/createtables.sql")
> var table = ""
> var havePrime = false
>
> s.getLines.foreach( (line) => {
> if(line.trim.toLowerCase.startsWith("create")) {
> createStatement = true
> createArr = line.split("`")
> if(createArr.length > 1) {
> table = createArr.apply(1)
> out.write("drop table if exists '"+table+"';\n")
> out.write("create table '"+table+"' (\n")
> }
> }
>
> if(createStatement && line.trim.startsWith(")")) {
> createStatement = false
> var first = true
> var havePrimeKey = false
> createStatArr.foreach( (stat) => {
> if(!first)
> out.write(",\n")
> out.write("\t"+stat.toString())
> first = false
> })
> out.write("\n);\n\n")
> createStatArr = new ArrayBuffer[Statement]
> havePrime = false
> }
>
> if(createStatement) {
> if(!(line.trim.toLowerCase.startsWith("create") ||
> line.trim.toLowerCase.startsWith("primary key") ||
> line.trim.toLowerCase.startsWith("unique key") ||
> line.trim.toLowerCase.startsWith("key") ||
> line.trim.toLowerCase.startsWith("constraint"))
> ) {
>
> createArr = line.trim.split(' ')
> var stat = new Statement
>
> if(createArr.length > 1) {
> stat.name = createArr.apply(0)
> var linestr = createArr.apply(1)
> if(linestr.endsWith(","))
> linestr = linestr.substring(0, linestr.length()-1);
> stat.sqltype = linestr
>
> if(createArr.apply(1).startsWith("enum"))
> stat.sqltype = "varchar(9)"
> if(line.indexOf("NOT NULL") != -1)
> stat.notNullable = true
> if(line.toLowerCase().indexOf("auto_increment") != -1)
> {
> stat.autoincrement = true
> havePrime = true
> }
>
> for(i <- 0 until createArr.length) {
> if(createArr.apply(i).compareToIgnoreCase("default") == 0) {
> var linestr = createArr.apply(i+1)
> if(linestr.endsWith(","))
> linestr = linestr.substring(0, linestr.length()-1);
> if(linestr.compareTo("CURRENT_TIMESTAMP") == 0)
> linestr = "'0000-00-00 00:00:00'"
> if(linestr.compareTo("'0000-00-00") == 0)
> linestr = "'0000-00-00 00:00:00'"
> stat.default = linestr
> }
> }
> createStatArr += stat
> }
> }
>
> if(
> line.trim.toLowerCase.startsWith("primary key") ||
> line.trim.toLowerCase.startsWith("constraint")
> ) {
> var stat = new Statement
> var linestr = line.trim()
>
> stat.sqlStr = line.trim
> if(linestr.endsWith(",")) {
> stat.sqlStr = linestr.substring(0, linestr.length()-1);
> }
> if(!havePrime || linestr.indexOf("PRIMARY") == -1)
> createStatArr += stat
> }
> }
>
> })
>
> out.close
> }
> -------------------------------------------------------------------------
> END
> --------------------------------------------------------------------------
>
> -------------------------------------------------------------------------
> CUT
> --------------------------------------------------------------------------
> CREATE TABLE `table1` (
> `oneId` int(11) unsigned NOT NULL AUTO_INCREMENT,
> `anotherId` int(11) unsigned NOT NULL,
> `creationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
> CURRENT_TIMESTAMP,
> `theblob` blob NOT NULL,
> `hashKey` varchar(16) NOT NULL,
> PRIMARY KEY (`oneId`),
> UNIQUE KEY `hashKey` (`hashKey`)
> ) ENGINE=InnoDB AUTO_INCREMENT=240 DEFAULT CHARSET=latin1;
> /*!40101 SET character_set_client = @saved_cs_client */;
>
> --
Thu, 2012-02-09, 07:31
#4
Re: Java developer new to Scala
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Am 08.02.2012 20:39, schrieb Daniel Persson:
> My background is in java development so I thought scala should not be that
> hard to learn.
>
> I think there isn't a better way to learn an new language than to have an
> actual problem to solve. So the issue I've looked into is to build a simple
> text parser to change data from MySQL dump file to a format that sqlite
> would consider correct for init of an database.
I think in the beginning, shorter problems are better suited. The
language features aren't that hard to learn, but the different habit,
like avoiding vars, like posted before. The 99 scala Problems are a nice
exercise: http://aperiodic.net/phil/scala/s-99/
Your code looks to me like a big, big mess.
What does that big method-like object do? Is everything related with
everything, or can some things been extracted? I would prefer much, much
smaller methods with simple tasks.
line.trim.toLowerCase.startsWith (something) is repeated all over the
place. Did you hear of the DRY principle?
A useful way to deal with lists comes to my mind, to simplify the search
for a keyword:
val keywords = List ("create", "primary key", "unique key", "key",
"constraint")
val normalizedLine = line.trim.toLowerCase
if (! (keywords.exists (kw => normalizedLine.startsWith (kw))) {
Lists/Seq/Vector/Map and all the collections have very useful stuff.
Their usage is very different from Javaland.
Thu, 2012-02-09, 17:11
#5
Re: Java developer new to Scala
One weak point is your initialization code for Statement which is scattered all over the place. If you follow the advice of using val your essentially force yourself to keep it structured. I have the same problem with some old graph code and tracing bugs for unintended state change in vars is fairly annoying. The drawbacks of val are sometimes increased memory usage due to copying but there you can read up on persistent data-structures optimized for sharing data.
On 8 February 2012 20:39, Daniel Persson <mailto.woden@gmail.com> wrote:
On 8 February 2012 20:39, Daniel Persson <mailto.woden@gmail.com> wrote:
Hi people.
My background is in java development so I thought scala should not be that hard to learn.
I think there isn't a better way to learn an new language than to have an actual problem to solve. So the issue I've looked into is to build a simple text parser to change data from MySQL dump file to a format that sqlite would consider correct for init of an database.
My goal of this mail isn't to ask for an solution. I just wanted to get some hints or tips on which concepts to look future into to improve my code. At the moment I've implemented code that could gather all the create statements and create the tables in sqlite.
I'll add my code and an example of an dump from mysql so you'll see what kind of data that could occur during this processing. The code is quite adhoc at the moment so I know I could do alot of simplifications. But because I don't know the language that well and don't have any scala developers closeby so I can't get hints, tips, tricks or pointers to improve either.
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
import scala.io._
import scala.collection.mutable.ArrayBuffer
class Statement {
var name = ""
var sqltype = ""
var notNullable = false
var default = ""
var autoincrement = false
var sqlStr = ""
var havePrimeKey = false
override def toString :String = {
if(sqlStr != "")
return sqlStr
if(autoincrement && sqltype.indexOf("int") != -1)
sqltype = "integer primary key autoincrement"
var str = name+" "+sqltype
if(notNullable)
str += " NOT NULL"
if(default != "")
str += " DEFAULT "+default
return str
}
}
object ReadFile extends Application {
// val s = Source.fromFile("dump.sql", "UTF-8")
val s = Source.fromFile("dump2.sql", "UTF-8")
var createArr = new Array[String](3)
var createStatArr = new ArrayBuffer[Statement]
var createStatement = false
val out = new java.io.FileWriter("c:/temp/sqltest/createtables.sql")
var table = ""
var havePrime = false
s.getLines.foreach( (line) => {
if(line.trim.toLowerCase.startsWith("create")) {
createStatement = true
createArr = line.split("`")
if(createArr.length > 1) {
table = createArr.apply(1)
out.write("drop table if exists '"+table+"';\n")
out.write("create table '"+table+"' (\n")
}
}
if(createStatement && line.trim.startsWith(")")) {
createStatement = false
var first = true
var havePrimeKey = false
createStatArr.foreach( (stat) => {
if(!first)
out.write(",\n")
out.write("\t"+stat.toString())
first = false
})
out.write("\n);\n\n")
createStatArr = new ArrayBuffer[Statement]
havePrime = false
}
if(createStatement) {
if(!(line.trim.toLowerCase.startsWith("create") ||
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("unique key") ||
line.trim.toLowerCase.startsWith("key") ||
line.trim.toLowerCase.startsWith("constraint"))
) {
createArr = line.trim.split(' ')
var stat = new Statement
if(createArr.length > 1) {
stat.name = createArr.apply(0)
var linestr = createArr.apply(1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
stat.sqltype = linestr
if(createArr.apply(1).startsWith("enum"))
stat.sqltype = "varchar(9)"
if(line.indexOf("NOT NULL") != -1)
stat.notNullable = true
if(line.toLowerCase().indexOf("auto_increment") != -1) {
stat.autoincrement = true
havePrime = true
}
for(i <- 0 until createArr.length) {
if(createArr.apply(i).compareToIgnoreCase("default") == 0) {
var linestr = createArr.apply(i+1)
if(linestr.endsWith(","))
linestr = linestr.substring(0, linestr.length()-1);
if(linestr.compareTo("CURRENT_TIMESTAMP") == 0)
linestr = "'0000-00-00 00:00:00'"
if(linestr.compareTo("'0000-00-00") == 0)
linestr = "'0000-00-00 00:00:00'"
stat.default = linestr
}
}
createStatArr += stat
}
}
if(
line.trim.toLowerCase.startsWith("primary key") ||
line.trim.toLowerCase.startsWith("constraint")
) {
var stat = new Statement
var linestr = line.trim()
stat.sqlStr = line.trim
if(linestr.endsWith(",")) {
stat.sqlStr = linestr.substring(0, linestr.length()-1);
}
if(!havePrime || linestr.indexOf("PRIMARY") == -1)
createStatArr += stat
}
}
})
out.close
}
------------------------------------------------------------------------- END --------------------------------------------------------------------------
------------------------------------------------------------------------- CUT --------------------------------------------------------------------------
CREATE TABLE `table1` (
`oneId` int(11) unsigned NOT NULL AUTO_INCREMENT,
`anotherId` int(11) unsigned NOT NULL,
`creationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`theblob` blob NOT NULL,
`hashKey` varchar(16) NOT NULL,
PRIMARY KEY (`oneId`),
UNIQUE KEY `hashKey` (`hashKey`)
) ENGINE=InnoDB AUTO_INCREMENT=240 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `table1`
--
LOCK TABLES `table1` WRITE;
/*!40000 ALTER TABLE `table1` DISABLE KEYS */;
INSERT INTO `table1` VALUES (1,2,'2010-08-06 11:52:54',0xfaff80988e80eee7798,'fafasd'),(2,142456,'2010-07-30 11:11:29',0xfaff80988e80eee7798,'asfaew'),(3,220748,'2010-08-03 06:16:24',0xfaff80988e80eee7798,'ar5hffgadbf');
/*!40000 ALTER TABLE `table1` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `table2`
--
DROP TABLE IF EXISTS `table2`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `table2` (
`timestamp` bigint(20) NOT NULL DEFAULT '0',
`type` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL DEFAULT '0',
`data1` int(11) NOT NULL DEFAULT '0',
`blob1` blob,
`blob2` blob,
`bool` tinyint(1) NOT NULL DEFAULT '0',
KEY `table2Key1` (`type`),
KEY `table2Key2` (`id`),
KEY `table2Key3` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--------------------------------------------------------------------------END --------------------------------------------------------------------------
Best regards
Daniel
a) only vals, no vars
b) only use immutable collections, do not change anything.
c) without all the ifs. use pattern matching instead.
a+b seem strange at first when coming from traditional java, but once you get the hang of it, every piece of imperative code will look like a hack. at least it does to me.
and i would suggest to add:
d) parse the stuff into an actual model (that usually ends up being a tree) representing the statements so you could easily change the output format if you wanted
to that list
Am 08.02.2012 20:39, schrieb Daniel Persson: