I have created the database in SQL lite and improved the little program to handle it (list, add, remove records). At this point I am trying to list the contents from the database using the prepared statement step() function. However, I can't iterate over the rows and columns on the database.
I suspect that the reason for that is that I am not handling the statement appropriately in this line:
stmt:Sqlite.Statement = null
If that is the case, how to pass the statement from the main (init) function to the children function?
This is the entire code so far:
// Trying to do a cookbook program
// raw_imput for Genie included, compile with valac --pkg sqlite3 cookbook.gs
[indent=4]
uses Sqlite
def raw_input (query:string = ""):string
stdout.printf ("%s", query)
return stdin.read_line ()
init
db : Sqlite.Database? = null
if (Sqlite.Database.open ("cookbook.db3", out db) != Sqlite.OK)
stderr.printf ("Error: %d: %s \n", db.errcode (), db.errmsg ())
Process.exit (-1)
loop:bool = true
while loop = true
print "==================================================="
print " RECIPE DATABASE "
print " 1 - Show All Recipes"
print " 2 - Search for a recipe"
print " 3 - Show a Recipe"
print " 4 - Delete a recipe"
print " 5 - Add a recipe"
print " 6 - Print a recipe"
print " 0 - Exit"
print "==================================================="
response:string = raw_input("Enter a selection -> ")
if response == "1" // Show All Recipes
PrintAllRecipes()
else if response is "2" // Search for a recipe
pass
else if response is "3" //Show a Recipe
pass
else if response is "4"//Delete a recipe
pass
else if response is "5" //Add a recipe
pass
else if response is "6" //Print a recipe
pass
else if response is "0" //Exit
print "Goodbye"
Process.exit (-1)
else
print "Unrecognized command. Try again."
def PrintAllRecipes ()
print "%-5s%-30s%-20s%-30s", "Item", "Name", "Serves", "Source"
print "--------------------------------------------------------------------------------------"
stmt:Sqlite.Statement = null
param_position:int = stmt.bind_parameter_index ("$UID")
//assert (param_position > 0)
stmt.bind_int (param_position, 1)
cols:int = stmt.column_count ()
while stmt.step () == Sqlite.ROW
for i:int = 0 to cols
i++
col_name:string = stmt.column_name (i)
val:string = stmt.column_text (i)
type_id:int = stmt.column_type (i)
stdout.printf ("column: %s\n", col_name)
stdout.printf ("value: %s\n", val)
stdout.printf ("type: %d\n", type_id)
/* while stmt.step () == Sqlite.ROW
col_item:string = stmt.column_name (1)
col_name:string = stmt.column_name (2)
col_serves:string = stmt.column_name (3)
col_source:string = stmt.column_name (4)
print "%-5s%-30s%-20s%-30s", col_item, col_name, col_serves, col_source */
Extra questions are:
Does the definitions of functions should come before or after init? I have noticed that they wouldn't be called if I left all of them after init. But by leaving raw_input in the beginning the error disappeared.
I was trying to define PrintAllRecipes() within a class, for didactic reasons. But I ended up making it "invisible" to the main routine.
Many thanks,
Yes, you need to assign a prepared statement, not null, to stmt. For example:
// Trying to do a cookbook program
// raw_input for Genie included, compile with
// valac --pkg sqlite3 --pkg gee-0.8 cookbook.gs
[indent=4]
uses Sqlite
init
db:Database
if (Database.open ("cookbook.db3", out db) != OK)
stderr.printf ("Error: %d: %s \n", db.errcode (), db.errmsg ())
Process.exit (-1)
while true
response:string = UserInterface.get_input_from_menu()
if response is "1" // Show All Recipes
PrintAllRecipes( db )
else if response is "2" // Search for a recipe
pass
else if response is "3" //Show a Recipe
pass
else if response is "4"//Delete a recipe
pass
else if response is "5" //Add a recipe
pass
else if response is "6" //Print a recipe
pass
else if response is "0" //Exit
print "Goodbye"
break
else
print "Unrecognized command. Try again."
namespace UserInterface
def get_input_from_menu():string
show_menu()
return raw_input("Enter a selection -> ")
def raw_input (query:string = ""):string
stdout.printf ("%s", query)
return stdin.read_line ()
def show_menu()
print """===================================================
RECIPE DATABASE
1 - Show All Recipes
2 - Search for a recipe
3 - Show a Recipe
4 - Delete a recipe
5 - Add a recipe
6 - Print a recipe
0 - Exit
==================================================="""
namespace PreparedStatements
def select_all( db:Database ):Statement
statement:Statement
db.prepare_v2( """
select name, servings as serves, source from Recipes
""", -1, out statement )
return statement
def PrintAllRecipes ( db:Database )
print "%-5s%-30s%-20s%-30s", "Item", "Name", "Serves", "Source"
print "--------------------------------------------------------------------------------------"
stmt:Statement = PreparedStatements.select_all( db )
cols:int = stmt.column_count ()
var row = new dict of string, string
item:int = 1
while stmt.step() == ROW
for i:int = 0 to (cols - 1)
row[ stmt.column_name( i ) ] = stmt.column_text( i )
stdout.printf( "%-5s", item.to_string( "%03i" ))
stdout.printf( "%-30s", row[ "name" ])
stdout.printf( "%-20s", row[ "serves" ])
stdout.printf( "%-30s\n", row[ "source" ])
item++
A few pointers
Generally you want to avoid assigning null. null is no value. For example a boolean can either be true or false and nothing else, but a variable that can have no value makes things more complicated.
a:bool? = null
if a == null
print "I'm a boolean variable, but I am neither true nor false???"
If you are looking to declare a variable in Genie before assigning a value, for example when calling a function with an out parameter, don't assign anything. I have changed db:Database to show this
Process.exit( -1 ) should probably be used sparingly and really only for error conditions that you want to signal to a calling command line script. I don't think a user selected exit from the program is such an error condition, so I have changed Process.exit( -1 ) to break for that
The definition of functions doesn't matter whether it is before or after init, I prefer to put them after so the first function that is called, i.e. init, is at the top and easy to read
A class is a data type and yes, it can have functions, but usually you need some data defined in the class and the function is written to act on that data. A function in a class is often called a 'method' and in the past with object oriented programming classes were defined to group methods together. These methods had no data to act on and are defined as 'static' methods. The modern practise is to mainly use static methods for creating more complex object constructors, look up 'factory' methods and creational design patterns. Instead to group functions, and other syntax, we use namespaces. I have used a couple of namespaces in the example. Usually a namespace is given its own file or files. If you are thinking of splitting your Genie project into more source files then take a look at https://wiki.gnome.org/Projects/Genie#A_Simple_Build_Script
A primary key should be internal to the database and would not be presented to a user, only a database administrator would be interested in such things. So I have changed 'item' in the output to be a count of the number of entries displayed
Genie and Vala bind the SQLite C interface. If you need more details on a particular function take a look at C-language Interface Specification for SQLite
Related
I Have the following model
class Process: Object {
#objc dynamic var processID:Int = 1
let steps = List<Step>()
}
class Step: Object {
#objc private dynamic var stepCode: Int = 0
#objc dynamic var stepDateUTC: Date? = nil
var stepType: ProcessStepType {
get {
return ProcessStepType(rawValue: stepCode) ?? .created
}
set {
stepCode = newValue.rawValue
}
}
}
enum ProcessStepType: Int { // to review - real value
case created = 0
case scheduled = 1
case processing = 2
case paused = 3
case finished = 4
}
A process can start, processing , paused , resume (to be in step processing again), pause , resume again,etc. the current step is the one with the latest stepDateUTC
I am trying to get all Processes, having for last step ,a step of stepType processing "processing ", ie. where for the last stepDate, stepCode is 2 .
I came with the following predicate... which doesn't work. Any idea of the right perform to perform such query ?
my best trial is the one. Is it possible to get to this result via one realm query .
let processes = realm.objects(Process.self).filter(NSPredicate(format: "ANY steps.stepCode = 2 AND NOT (ANY steps.stepCode = 4)")
let ongoingprocesses = processes.filter(){$0.steps.sorted(byKeyPath: "stepDateUTC", ascending: false).first!.stepType == .processing}
what I hoped would work
NSPredicate(format: "steps[LAST].stepCode = \(TicketStepType.processing.rawValue)")
I understand [LAST] is not supported by realm (as per the cheatsheet). but is there anyway around I could achieve my goal through a realm query?
There are a few ways to approach this and it doesn't appear the date property is relevant because lists are stored in sequential order (as long as they are not altered), so the last element in the List was added last.
This first piece of code will filter for processes where the last element is 'processing'. I coded this long-handed so the flow is more understandable.
let results = realm.objects(Process.self).filter { p in
let lastIndex = p.steps.count - 1
let step = p.steps[lastIndex]
let type = step.stepType
if type == .processing {
return true
}
return false
}
Note that Realm objects are lazily loaded - which means thousands of objects have a low memory impact. By filtering using Swift, the objects are filtered in memory so the impact is more significant.
The second piece of code is what I would suggest as it makes filtering much simpler, but would require a slight change to the Process model.
class Process: Object {
#objc dynamic var processID:Int = 1
let stepHistory = List<Step>() //RENAMED: the history of the steps
#objc dynamic var name = ""
//ADDED: new property tracks current step
#objc dynamic var current_step = ProcessStepType.created.index
}
My thought here is that the Process model keeps a 'history' of steps that have occurred so far, and then what the current_step is.
I also modified the ProcessStepType enum to make it more filterable friendly.
enum ProcessStepType: Int { // to review - real value
case created = 0
case scheduled = 1
case processing = 2
case paused = 3
case finished = 4
//this is used when filtering
var index: Int {
switch self {
case .created:
return 0
case .scheduled:
return 1
case .processing:
return 2
case .paused:
return 3
case .finished:
return 4
}
}
}
Then to return all processes where the last step in the list is 'processing' here's the filter
let results2 = realm.objects(Process.self).filter("current_step == %#", ProcessStepType.processing.index)
The final thought is to add some code to the Process model so when a step is added to the list, the current_step var is also updated. Coding that is left to the OP.
I am new to go and trying to retrieve data from a sqlite database.
Im using github.com/mattn/go-sqlite3 as sqlite driver.
The query I m sending does not return any results even though it should. I tried the query my programme is generating manually and it returns data as it should when I use the query manually as well as when I send it via my programme.
Here is my code:
for index := range Array {
id, _ := strconv.Atoi(Array[index])
rand.Seed(time.Now().UnixNano())
RandomNr := rand.Intn(100)
fmt.Printf("index: %d - randomnr: %d \n", id, RandomNr)
rows, errROW := db.Query("SELECT user.id,user.name,stage.link,player.url,player.characterchance,player.chance FROM user,stage,player WHERE user.id = '%d' AND '%d' <= user.chance AND stage.user = user.id AND stage.domain = player.id AND player.chance > 0 ORDER BY player.id ASC \n",id, RandomNr)//.Scan(&idr, &name, &link, &url, &characterchance, &chance)
//this is what the finished query looks like and it returns the rows as its supposed to
//rows, errROW := db.Query("SELECT user.id,user.name,stage.link,player.url,player.characterchance,player.chance FROM user,stage,player WHERE user.id = '203' AND '33' <= user.chance AND stage.user = user.id AND stage.domain = player.id AND player.chance > 0 ORDER BY player.id ASC")
if errROW != nil {
fmt.Println("errROW")
log.Println(errROW)
}
defer rows.Close()
if rows.Next() == false {
fmt.Println("no rows ")
}
for rows.Next() {
fmt.Println("where are the rows")
var id int
var name string
var link string
var url string
var characterchance int
var chance int
rows.Scan(&id, &name, &link, &url, &characterchance, &chance)
fmt.Println(id,name,link,url,characterchance,chance)
}
rows.Close()
}
}
This query can return multiple and single rows. I also tried retrieving the data via QueryRow as a single row which also did not return any result.
Any help would be much appreciated.
UPDATE:
I added
if rows.Next() == false
as an attempt to find the problem. Removing it yields the same result. Furthermore I do not get an error message from scan. The for rows.next() loop does not even get executed.
when you do:
if rows.Next() == false
you are scrolling to the first row
and
for rows.Next()
moves to the next row
basically, you are skipping the first row in your result set in the example code you provided.
also, you are ignoring the error in Scan.
This looks like it would print something if the query returns at least 2 rows (since first row is being skipped)
Ok I figured out what the problem was:
In my query I used: %d as a placeholder for my variable when I should have used $1,$2 etc. Using this the query returns results as expected.
It seems strange to me that this behaviour is allowed returns no error from go or sqlite and even works when you just printout the query and use it with sqlite3 manually. Coming from C and just starting out with go this can obviously be the cause for some headaches.
I am using Swift in a project, and using SQLite.swift for database handling. I am trying to retrieve the most recent entry from my database like below:
func returnLatestEmailAddressFromEmailsTable() -> String{
let dbPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first as String
let db = Database("\(dbPath)/db.sqlite3")
let emails = db["emails"]
let email = Expression<String>("email")
let time = Expression<Int>("time")
var returnEmail:String = ""
for res in emails.limit(1).order(time.desc) {
returnEmail = res[email]
println("from inside: \(returnEmail)")
}
return returnEmail
}
I am trying to test the returned string from the above function like this:
println("from outside: \(returnLatestEmailAddressFromEmailsTable())")
Note how I print the value from both inside and outside of the function. Inside, it works every single time. I am struggling with the "from outside:" part.
Sometimes the function returns the correct email, but sometimes it returns "" (presumably, the value was not set in the for loop).
How can I add "blocking" functionality so calling returnLatestEmailAddressFromEmailsTable() will always first evaluate the for loop, and only after this return the value?
I have a very simple task I am trying to do in Groovy but cannot seem to get it to work. I am just trying to loop through a map object in groovy and print out the key and value but this code does not work.
// A simple map
def map = [
iPhone : 'iWebOS',
Android: '2.3.3',
Nokia : 'Symbian',
Windows: 'WM8'
]
// Print the values
for (s in map) {
println s + ": " + map[s]
}
I am trying to get the output to look like this:
iPhone: iWebOS
Android: 2.3.3
Nokia: Symbian
Windows: WM8
Could someone please elaborate on how to do this??
Quite simple with a closure:
def map = [
'iPhone':'iWebOS',
'Android':'2.3.3',
'Nokia':'Symbian',
'Windows':'WM8'
]
map.each{ k, v -> println "${k}:${v}" }
Alternatively you could use a for loop as shown in the Groovy Docs:
def map = ['a':1, 'b':2, 'c':3]
for ( e in map ) {
print "key = ${e.key}, value = ${e.value}"
}
/*
Result:
key = a, value = 1
key = b, value = 2
key = c, value = 3
*/
One benefit of using a for loop as opposed to an each closure is easier debugging, as you cannot hit a break point inside an each closure (when using Netbeans).
When using the for loop, the value of s is a Map.Entry element, meaning that you can get the key from s.key and the value from s.value
Another option:
def map = ['a':1, 'b':2, 'c':3]
map.each{
println it.key +" "+ it.value
}
Does Scala support something like dynamic properties? Example:
val dog = new Dynamic // Dynamic does not define 'name' nor 'speak'.
dog.name = "Rex" // New property.
dog.speak = { "woof" } // New method.
val cat = new Dynamic
cat.name = "Fluffy"
cat.speak = { "meow" }
val rock = new Dynamic
rock.name = "Topaz"
// rock doesn't speak.
def test(val animal: Any) = {
animal.name + " is telling " + animal.speak()
}
test(dog) // "Rex is telling woof"
test(cat) // "Fluffy is telling meow"
test(rock) // "Topaz is telling null"
What is the closest thing from it we can get in Scala? If there's something like "addProperty" which allows using the added property like an ordinary field, it would be sufficient.
I'm not interested in structural type declarations ("type safe duck typing"). What I really need is to add new properties and methods at runtime, so that the object can be used by a method/code that expects the added elements to exist.
Scala 2.9 will have a specially handled Dynamic trait that may be what you are looking for.
This blog has a big about it: http://squirrelsewer.blogspot.com/2011/02/scalas-upcoming-dynamic-capabilities.html
I would guess that in the invokeDynamic method you will need to check for "name_=", "speak_=", "name" and "speak", and you could store values in a private map.
I can not think of a reason to really need to add/create methods/properties dynamically at run-time unless dynamic identifiers are also allowed -and/or- a magical binding to an external dynamic source (JRuby or JSON are two good examples).
Otherwise the example posted can be implemented entirely using the existing static typing in Scala via "anonymous" types and structural typing. Anyway, not saying that "dynamic" wouldn't be convenient (and as 0__ pointed out, is coming -- feel free to "go edge" ;-).
Consider:
val dog = new {
val name = "Rex"
def speak = { "woof" }
}
val cat = new {
val name = "Fluffy"
def speak = { "meow" }
}
// Rock not shown here -- because it doesn't speak it won't compile
// with the following unless it stubs in. In both cases it's an error:
// the issue is when/where the error occurs.
def test(animal: { val name: String; def speak: String }) = {
animal.name + " is telling " + animal.speak
}
// However, we can take in the more general type { val name: String } and try to
// invoke the possibly non-existent property, albeit in a hackish sort of way.
// Unfortunately pattern matching does not work with structural types AFAIK :(
val rock = new {
val name = "Topaz"
}
def test2(animal: { val name: String }) = {
animal.name + " is telling " + (try {
animal.asInstanceOf[{ def speak: String }).speak
} catch { case _ => "{very silently}" })
}
test(dog)
test(cat)
// test(rock) -- no! will not compile (a good thing)
test2(dog)
test2(cat)
test2(rock)
However, this method can quickly get cumbersome (to "add" a new attribute one would need to create a new type and copy over the current data into it) and is partially exploiting the simplicity of the example code. That is, it's not practically possible to create true "open" objects this way; in the case for "open" data a Map of sorts is likely a better/feasible approach in the current Scala (2.8) implementation.
Happy coding.
First off, as #pst pointed out, your example can be entirely implemented using static typing, it doesn't require dynamic typing.
Secondly, if you want to program in a dynamically typed language, program in a dynamically typed language.
That being said, you can actually do something like that in Scala. Here is a simplistic example:
class Dict[V](args: (String, V)*) extends Dynamic {
import scala.collection.mutable.Map
private val backingStore = Map[String, V](args:_*)
def typed[T] = throw new UnsupportedOperationException()
def applyDynamic(name: String)(args: Any*) = {
val k = if (name.endsWith("_=")) name.dropRight(2) else name
if (name.endsWith("_=")) backingStore(k) = args.first.asInstanceOf[V]
backingStore.get(k)
}
override def toString() = "Dict(" + backingStore.mkString(", ") + ")"
}
object Dict {
def apply[V](args: (String, V)*) = new Dict(args:_*)
}
val t1 = Dict[Any]()
t1.bar_=("quux")
val t2 = new Dict("foo" -> "bar", "baz" -> "quux")
val t3 = Dict("foo" -> "bar", "baz" -> "quux")
t1.bar // => Some(quux)
t2.baz // => Some(quux)
t3.baz // => Some(quux)
As you can see, you were pretty close, actually. Your main mistake was that Dynamic is a trait, not a class, so you can't instantiate it, you have to mix it in. And you obviously have to actually define what you want it to do, i.e. implement typed and applyDynamic.
If you want your example to work, there are a couple of complications. In particular, you need something like a type-safe heterogenous map as a backing store. Also, there are some syntactic considerations. For example, foo.bar = baz is only translated into foo.bar_=(baz) if foo.bar_= exists, which it doesn't, because foo is a Dynamic object.