使用 Genie 打印 select 查询的结果

Printing the results from a select query with Genie

我有 (列出、添加、删除记录)。此时我正在尝试使用准备好的语句 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 */

额外的问题是:

非常感谢,

是的,您需要将准备好的语句分配给 stmt,而不是 null。例如:

// 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前还是后易于阅读
  • A class 是一种数据类型,是的,它可以具有函数,但通常您需要在 class 中定义一些数据,并编写函数来处理该数据。 class 中的函数通常称为 'method',过去在面向对象编程中,classes 被定义为将方法组合在一起。这些方法没有可操作的数据,被定义为 'static' 方法。现代的做法是主要使用静态方法来创建更复杂的对象构造函数,查找 'factory' 方法和创建设计模式。我们使用名称空间来代替对函数和其他语法进行分组。我在示例中使用了几个名称空间。通常一个命名空间被赋予它自己的一个或多个文件。如果您正在考虑将 Genie 项目拆分为更多源文件,请查看 https://wiki.gnome.org/Projects/Genie#A_Simple_Build_Script
  • 主键应该是数据库内部的,不会呈现给用户,只有数据库管理员才会对这些东西感兴趣。所以我将输出中的 'item' 更改为显示条目数的计数
  • Genie 和 Vala 绑定 SQLite C 接口。如果您需要有关特定功能的更多详细信息,请查看 C-language Interface Specification for SQLite