File: spec-sql-list-objects.R

package info (click to toggle)
r-cran-dbitest 1.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,216 kB
  • sloc: sh: 10; makefile: 2
file content (157 lines) | stat: -rw-r--r-- 5,921 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#' spec_sql_list_objects
#' @family sql specifications
#' @usage NULL
#' @format NULL
#' @keywords NULL
spec_sql_list_objects <- list(
  list_objects_formals = function() {
    # <establish formals of described functions>
    expect_equal(names(formals(dbListObjects)), c("conn", "prefix", "..."))
  },

  list_objects_1 = function(ctx, con, table_name = "dbit06") {
    #' @return
    #' `dbListObjects()`
    objects <- dbListObjects(con)
    #' returns a data frame
    expect_s3_class(objects, "data.frame")
    #' with columns
    cols <- c("table", "is_prefix")
    #' `table` and `is_prefix` (in that order),
    expect_equal(names(objects)[seq_along(cols)], cols)
    #' optionally with other columns with a dot (`.`) prefix.
    expect_true(all(grepl("^[.]", names(objects)[-seq_along(cols)])))

    #' The `table` column is of type list.
    expect_equal(typeof(objects$table), "list")
    #' Each object in this list is suitable for use as argument in [dbQuoteIdentifier()].
    expect_error(map(objects$table, dbQuoteIdentifier, conn = con), NA)

    #' The `is_prefix` column is a logical.
    expect_type(objects$is_prefix, "logical")

    #' This data frame contains one row for each object (schema, table
    expect_false(table_name %in% objects)
    #' and view)
    # TODO
    #' accessible from the prefix (if passed) or from the global namespace
    #' (if prefix is omitted).

    #' Tables added with [dbWriteTable()] are
    penguins <- get_penguins(ctx)
    dbWriteTable(con, table_name, penguins)

    #' part of the data frame.
    objects <- dbListObjects(con)
    quoted_tables <- map_chr(objects$table, dbQuoteIdentifier, conn = con)
    expect_true(dbQuoteIdentifier(con, table_name) %in% quoted_tables)
  },
  # second stage
  list_objects_2 = function(ctx, con) {
    # table_name not in formals on purpose: this means that this table won't be
    # removed at the end of the test
    table_name <- "dbit06"

    #' As soon a table is removed from the database,
    #' it is also removed from the data frame of database objects.
    objects <- dbListObjects(con)
    quoted_tables <- map_chr(objects$table, dbQuoteIdentifier, conn = con)
    expect_false(dbQuoteIdentifier(con, table_name) %in% quoted_tables)
  },

  #'
  list_objects_temporary = function(ctx, con, table_name) {
    #' The same applies to temporary objects if supported by the database.
    if (isTRUE(ctx$tweaks$temporary_tables) && isTRUE(ctx$tweaks$list_temporary_tables)) {
      dbWriteTable(con, table_name, data.frame(a = 1L), temporary = TRUE)

      objects <- dbListObjects(con)
      quoted_tables <- map_chr(objects$table, dbQuoteIdentifier, conn = con)
      expect_true(dbQuoteIdentifier(con, table_name) %in% quoted_tables)
    }
  },

  #'
  list_objects_quote = function(ctx, con) {
    #' The returned names are suitable for quoting with `dbQuoteIdentifier()`.
    if (isTRUE(ctx$tweaks$strict_identifier)) {
      table_names <- "a"
    } else {
      table_names <- c("a", "with spaces", "with,comma")
    }

    for (table_name in table_names) {
      local_remove_test_table(con, table_name)
      dbWriteTable(con, dbQuoteIdentifier(con, table_name), data.frame(a = 2L))
      objects <- dbListObjects(con)
      quoted_tables <- map_chr(objects$table, dbQuoteIdentifier, conn = con)
      expect_true(dbQuoteIdentifier(con, table_name) %in% quoted_tables)
    }
  },

  #'
  list_objects_closed_connection = function(ctx, closed_con) {
    #' @section Failure modes:
    #' An error is raised when calling this method for a closed
    expect_error(dbListObjects(closed_con))
  },

  list_objects_invalid_connection = function(ctx, invalid_con) {
    #' or invalid connection.
    expect_error(dbListObjects(invalid_con))
  },

  list_objects_features = function(ctx, con) {
    #' @section Specification:
    objects <- dbListObjects(con)

    #' The `prefix` column indicates if the `table` value refers to a table
    #' or a prefix.
    #' For a call with the default `prefix = NULL`, the `table`
    #' values that have `is_prefix == FALSE` correspond to the tables
    #' returned from [dbListTables()],
    non_prefix_objects <- map_chr(
      objects$table[!objects$is_prefix],
      dbQuoteIdentifier,
      conn = con
    )
    all_tables <- dbQuoteIdentifier(con, dbListTables(con))
    expect_equal(sort(non_prefix_objects), sort(as.character(all_tables)))

    #'
    #' The `table` object can be quoted with [dbQuoteIdentifier()].
    sql <- map(objects$table[!objects$is_prefix], dbQuoteIdentifier, conn = con)
    #' The result of quoting can be passed to [dbUnquoteIdentifier()].
    expect_error(walk(sql, dbUnquoteIdentifier, conn = con), NA)
    #' (For backends it may be convenient to use the [Id] class, but this is
    #' not required.)

    if (!any(objects$is_prefix)) {
      skip("No schemas available")
    }

    #'
    #' Values in `table` column that have `is_prefix == TRUE` can be
    #' passed as the `prefix` argument to another call to `dbListObjects()`.
    #' For the data frame returned from a `dbListObject()` call with the
    #' `prefix` argument set, all `table` values where `is_prefix` is
    #' `FALSE` can be used in a call to [dbExistsTable()] which returns
    #' `TRUE`.
    for (schema in utils::head(objects$table[objects$is_prefix])) {
      sub_objects <- dbListObjects(con, prefix = schema)
      for (sub_table in utils::head(sub_objects$table[!sub_objects$is_prefix])) {
        # HACK HACK HACK for RMariaDB on OS X (#188)
        if (!identical(sub_table, Id(schema = "information_schema", table = "FILES"))) {
          # eval(bquote()) preserves the SQL class, even if it's not apparent
          # in the output
          eval(bquote(expect_true(
            dbExistsTable(con, .(sub_table)),
            label = paste0("dbExistsTable(", dbQuoteIdentifier(con, sub_table), ")")
          )))
        }
      }
    }
  },
  #
  NULL
)