Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci_pr_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
- name: 🧪 Test - PG ${{ matrix.pg }}
run: pgrx-build-test
- name: 📎 Clippy - PG ${{ matrix.pg }}
if: ${{ matrix.pg == '18' }}
if: ${{ matrix.pg == '15' }}
run: cargo clippy --color always -- --deny warnings --allow unexpected-cfgs
format:
name: 🕵️ Format
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.DS_Store
.idea/
/target
/tests/pg_regress/results
/tests/pg_regress/regression.*
*.iml
**/*.rs.bk
Cargo.lock
2 changes: 1 addition & 1 deletion CONTRIBUTING
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Here are some hints to prepare your environment to contribute to the project:

- Install git (pre-commit)[https://pre-commit.com/] hooks with `pre-commit install`
- Start a PG with the extension `cargo pgrx run`
- Run tests with `cargo test`
- Run tests with `cargo pgrx regress` (use options --resetdb to force the reset of the db, and --auto to automatically update the expected results)
- Format with `cargo fmt`
- Lint with `cargo clippy`

Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ name = "pgrx_embed_pg_no_seqscan"
path = "./src/bin/pgrx_embed.rs"

[features]
default = ["pg18"]
default = ["pg15"]
pg14 = ["pgrx/pg14", "pgrx-tests/pg14" ]
pg15 = ["pgrx/pg15", "pgrx-tests/pg15" ]
pg16 = ["pgrx/pg16", "pgrx-tests/pg16" ]
Expand All @@ -35,5 +35,8 @@ opt-level = 3
lto = "fat"
codegen-units = 1

[package.metadata.pgrx.regress]
enabled = true

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(pgrx_embed)'] }
12 changes: 12 additions & 0 deletions Makefile
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is necessary for pgxn/pgxn-tools to trigger pg regress tests.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
PG_CONFIG ?= $(shell which pg_config)
DISTNAME = $(shell perl -nE '/^name\s*=\s*"([^"]+)/ && do { say $$1; exit }' Cargo.toml)
DISTVERSION = $(shell perl -nE '/^version\s*=\s*"([^"]+)/ && do { say $$1; exit }' Cargo.toml)
PGRXV = $(shell perl -nE '/^pgrx\s+=\s"=?([^"]+)/ && do { say $$1; exit }' Cargo.toml)
PGV = $(shell perl -E 'shift =~ /(\d+)/ && say $$1' "$(shell $(PG_CONFIG) --version)")
EXTRA_CLEAN = META.json $(DISTNAME)-$(DISTVERSION).zip target
TESTS = $(wildcard tests/pg_regress/sql/*.sql)
REGRESS = $(patsubst tests/pg_regress/sql/%.sql,%,$(TESTS))
REGRESS_OPTS = --inputdir=tests/pg_regress --outputdir=target/installcheck

PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
2 changes: 1 addition & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub unsafe fn resolve_table_name(table_oid: Oid) -> Option<String> {

pub unsafe fn current_db_name() -> String {
let db_oid = pg_sys::MyDatabaseId;
string_from_ptr(pg_sys::get_database_name(db_oid)).unwrap()
string_from_ptr(pg_sys::get_database_name(db_oid)).expect("Failed to get database name")
}

pub unsafe fn current_username() -> String {
Expand Down
78 changes: 38 additions & 40 deletions src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use pgrx::pg_sys::{
ProcessUtilityContext, QueryCompletion, QueryDesc, QueryEnvironment, SeqScan,
};
use pgrx::{error, notice, pg_guard, pg_sys, PgBox, PgRelation};
#[allow(deprecated)]
use regex::Regex;

use crate::guc::DetectionLevelEnum;
Expand Down Expand Up @@ -45,7 +44,6 @@ impl NoSeqscanHooks {
unsafe {
if let Some(node) = plan.as_ref() {
self.check_current_node(plan, rtables);

self.check_plan_recursively(node.lefttree, rtables);
self.check_plan_recursively(node.righttree, rtables);
}
Expand Down Expand Up @@ -73,68 +71,67 @@ Query: {}
fn get_query_string(&self, query_desc: &PgBox<QueryDesc>) -> String {
unsafe { CStr::from_ptr(query_desc.sourceText) }
.to_str()
.unwrap()
.expect("Invalid UTF-8 in query string")
.to_string()
.to_lowercase()
}

fn is_ignored_query_for_comment(&mut self, query_string: &str) -> bool {
let re = Regex::new(r"/\*.*pg_no_seqscan_skip.*\*/").unwrap();
re.is_match(query_string)
}

fn is_ignored_user(&mut self, current_user: String) -> bool {
match guc::PG_NO_SEQSCAN_IGNORE_USERS.get() {
Some(ignore_users_setting) => {
fn is_ignored_user(&self, current_user: String) -> bool {
guc::PG_NO_SEQSCAN_IGNORE_USERS
.get()
.map(|ignore_users_setting| {
comma_separated_list_contains(ignore_users_setting, current_user)
}
None => unreachable!(),
}
})
.unwrap()
}

fn is_checked_database(&mut self, database: String) -> bool {
match guc::PG_NO_SEQSCAN_CHECK_DATABASES.get() {
Some(check_databases_setting) => {
fn is_checked_database(&self, database: String) -> bool {
guc::PG_NO_SEQSCAN_CHECK_DATABASES
.get()
.map(|check_databases_setting| {
check_databases_setting.is_empty()
|| comma_separated_list_contains(check_databases_setting, database)
}
None => unreachable!(),
}
})
.unwrap()
}

fn is_checked_schema(&mut self, schema: String) -> bool {
match guc::PG_NO_SEQSCAN_CHECK_SCHEMAS.get() {
Some(check_schemas_setting) => {
fn is_checked_schema(&self, schema: String) -> bool {
guc::PG_NO_SEQSCAN_CHECK_SCHEMAS
.get()
.map(|check_schemas_setting| {
check_schemas_setting.is_empty()
|| comma_separated_list_contains(check_schemas_setting, schema)
}
None => unreachable!(),
}
})
.unwrap()
}

fn check_tables_options_is_set(&mut self) -> bool {
fn check_tables_options_is_set(&self) -> bool {
guc::PG_NO_SEQSCAN_CHECK_TABLES
.get()
.is_some_and(|tables| !tables.is_empty())
}

fn is_checked_table(&mut self, table_name: String) -> bool {
match guc::PG_NO_SEQSCAN_CHECK_TABLES.get() {
Some(check_tables_setting) => {
fn is_checked_table(&self, table_name: String) -> bool {
guc::PG_NO_SEQSCAN_CHECK_TABLES
.get()
.map(|check_tables_setting| {
check_tables_setting.is_empty()
|| comma_separated_list_contains(check_tables_setting, table_name)
}
None => unreachable!(),
}
})
.unwrap()
}

fn is_ignored_table(&mut self, table_name: String) -> bool {
match guc::PG_NO_SEQSCAN_IGNORE_TABLES.get() {
Some(ignore_tables_setting) => {
fn is_ignored_table(&self, table_name: String) -> bool {
guc::PG_NO_SEQSCAN_IGNORE_TABLES
.get()
.map(|ignore_tables_setting| {
comma_separated_list_contains(ignore_tables_setting, table_name)
}
None => unreachable!(),
}
})
.unwrap()
}

unsafe fn check_current_node(&mut self, node: *mut Plan, rtables: *mut List) {
Expand All @@ -144,9 +141,11 @@ Query: {}

let seq_scan: &mut SeqScan = &mut *(node as *mut SeqScan);
#[cfg(not(feature = "pg14"))]
let table_oid = scanned_table(seq_scan.scan.scanrelid, rtables).unwrap();
let table_oid = scanned_table(seq_scan.scan.scanrelid, rtables)
.expect("Failed to get scanned table OID");
#[cfg(feature = "pg14")]
let table_oid = scanned_table(seq_scan.scanrelid, rtables).unwrap();
let table_oid =
scanned_table(seq_scan.scanrelid, rtables).expect("Failed to get scanned table OID");

if self.is_sequence(table_oid) {
return;
Expand All @@ -157,13 +156,12 @@ Query: {}
return;
}

let schema = resolve_namespace_name(table_oid).unwrap();
let schema = resolve_namespace_name(table_oid).expect("Failed to resolve schema name");
if !self.is_checked_schema(schema) {
return;
}

let table_name = resolve_table_name(table_oid);
let table_name = table_name.unwrap();
let table_name = resolve_table_name(table_oid).expect("Failed to resolve table name");

if !self.is_checked_table(table_name.clone()) {
return;
Expand Down
Loading