使用Genie从选择查询打印结果

时间:2015-10-17 23:17:32

标签: sqlite genie

我有created the database in SQL lite and improved the little program to handle it(列出,添加,删除记录)。此时,我正在尝试使用预准备语句step()函数列出数据库中的内容。但是,我无法遍历数据库中的行和列。

我怀疑其原因是我没有在这一行中恰当地处理该陈述:

stmt:Sqlite.Statement = null

如果是这种情况,如何将语句从main(init)函数传递给子函数?

到目前为止,这是完整的代码:

// 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 */

额外的问题是:

  • 函数的定义是应该在init之前还是之后?我注意到如果我在init之后将所有这些都留下,他们就不会被调用。但是通过将raw_input保留在开头,错误就消失了。

  • 出于教学原因,我试图在一个类中定义PrintAllRecipes()。但我最终把它变成了'#34;隐形"到主程序。

非常感谢,

1 个答案:

答案 0 :(得分:1)

是的,您需要为null分配一份准备好的陈述,而不是stmt。例如:

// 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++

一些指示

  • 通常,您希望避免分配nullnull没有价值。例如,布尔值可以是truefalse而不是其他任何东西,但是一个没有值的变量会使事情变得更复杂。

    a:bool? = null
    if a == null
        print "I'm a boolean variable, but I am neither true nor false???"
    

    如果您想在分配值之前在Genie中声明变量,例如在调用具有out参数的函数时,请不要分配任何内容。我已更改db:Database以显示此

  • Process.exit( -1 )应该谨慎使用,实际上只适用于您想要向调用命令行脚本发出信号的错误情况。我不认为用户选择从程序退出是错误的,所以我已将Process.exit( -1 )更改为break
  • 函数的定义并不重要,无论它是在init之前还是之后,我更喜欢将它们放在后面,因此调用的第一个函数,即init,位于顶部并且易于阅读
  • 类是一种数据类型,是的,它可以有函数,但通常需要在类中定义一些数据,并编写函数来处理该数据。类中的函数通常被称为“方法”'在过去,面向对象编程类被定义为将方法组合在一起。这些方法没有数据可以采取行动,并被定义为“静态”和“静态”。方法。现代的做法是主要使用静态方法来创建更复杂的对象构造函数,查找工厂'方法和创作设计模式。我们使用命名空间代替对函数和其他语法进行分组。我在示例中使用了几个名称空间。通常,命名空间被赋予自己的文件。如果您正在考虑将Genie项目拆分为更多源文件,请查看https://wiki.gnome.org/Projects/Genie#A_Simple_Build_Script
  • 主键应该是数据库的内部键,不会呈现给用户,只有数据库管理员会对此类内容感兴趣。所以我改变了' item'在输出中显示的条目数
  • Genie和Vala绑定SQLite C接口。如果您需要有关特定功能的更多详细信息,请查看 C-language Interface Specification for SQLite