【问题标题】:Printing the results from a select query with Genie使用 Genie 打印选择查询的结果
【发布时间】:2015-10-17 23:17:32
【问题描述】:

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

我怀疑这是因为我没有正确处理这一行中的语句:

stmt:Sqlite.Statement = null

如果是这样,如何将主(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之前还是之后?我注意到,如果我在初始化后离开所有这些,它们就不会被调用。但是通过在开头留下 raw_input,错误就消失了。

  • 出于教学原因,我试图在一个类中定义 PrintAllRecipes()。但我最终让它对主程序“不可见”。

非常感谢,

【问题讨论】:

    标签: sqlite genie


    【解决方案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
    • 主键应该是数据库内部的,不会提供给用户,只有数据库管理员才会对这些东西感兴趣。所以我将输出中的“项目”更改为显示的条目数
    • Genie 和 Vala 绑定 SQLite C 接口。如果您需要有关特定功能的更多详细信息,请查看 C-language Interface Specification for SQLite

    【讨论】:

      猜你喜欢
      • 2010-12-28
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多